Search in sources :

Example 1 with RelBuilder

use of org.apache.calcite.tools.RelBuilder in project flink by apache.

the class FlinkAggregateExpandDistinctAggregatesRule method onMatch.

//~ Methods ----------------------------------------------------------------
public void onMatch(RelOptRuleCall call) {
    final Aggregate aggregate = call.rel(0);
    if (!aggregate.containsDistinctCall()) {
        return;
    }
    // Find all of the agg expressions. We use a LinkedHashSet to ensure
    // determinism.
    int nonDistinctCount = 0;
    int distinctCount = 0;
    int filterCount = 0;
    int unsupportedAggCount = 0;
    final Set<Pair<List<Integer>, Integer>> argLists = new LinkedHashSet<>();
    for (AggregateCall aggCall : aggregate.getAggCallList()) {
        if (aggCall.filterArg >= 0) {
            ++filterCount;
        }
        if (!aggCall.isDistinct()) {
            ++nonDistinctCount;
            if (!(aggCall.getAggregation() instanceof SqlCountAggFunction || aggCall.getAggregation() instanceof SqlSumAggFunction || aggCall.getAggregation() instanceof SqlMinMaxAggFunction)) {
                ++unsupportedAggCount;
            }
            continue;
        }
        ++distinctCount;
        argLists.add(Pair.of(aggCall.getArgList(), aggCall.filterArg));
    }
    Preconditions.checkState(argLists.size() > 0, "containsDistinctCall lied");
    // arguments then we can use a more efficient form.
    if (nonDistinctCount == 0 && argLists.size() == 1) {
        final Pair<List<Integer>, Integer> pair = Iterables.getOnlyElement(argLists);
        final RelBuilder relBuilder = call.builder();
        convertMonopole(relBuilder, aggregate, pair.left, pair.right);
        call.transformTo(relBuilder.build());
        return;
    }
    if (useGroupingSets) {
        rewriteUsingGroupingSets(call, aggregate, argLists);
        return;
    }
    // we can generate multi-phase aggregates
    if (// one distinct aggregate
    distinctCount == 1 && // no filter
    filterCount == 0 && // sum/min/max/count in non-distinct aggregate
    unsupportedAggCount == 0 && nonDistinctCount > 0) {
        // one or more non-distinct aggregates
        final RelBuilder relBuilder = call.builder();
        convertSingletonDistinct(relBuilder, aggregate, argLists);
        call.transformTo(relBuilder.build());
        return;
    }
    // Create a list of the expressions which will yield the final result.
    // Initially, the expressions point to the input field.
    final List<RelDataTypeField> aggFields = aggregate.getRowType().getFieldList();
    final List<RexInputRef> refs = new ArrayList<>();
    final List<String> fieldNames = aggregate.getRowType().getFieldNames();
    final ImmutableBitSet groupSet = aggregate.getGroupSet();
    final int groupAndIndicatorCount = aggregate.getGroupCount() + aggregate.getIndicatorCount();
    for (int i : Util.range(groupAndIndicatorCount)) {
        refs.add(RexInputRef.of(i, aggFields));
    }
    // Aggregate the original relation, including any non-distinct aggregates.
    final List<AggregateCall> newAggCallList = new ArrayList<>();
    int i = -1;
    for (AggregateCall aggCall : aggregate.getAggCallList()) {
        ++i;
        if (aggCall.isDistinct()) {
            refs.add(null);
            continue;
        }
        refs.add(new RexInputRef(groupAndIndicatorCount + newAggCallList.size(), aggFields.get(groupAndIndicatorCount + i).getType()));
        newAggCallList.add(aggCall);
    }
    // In the case where there are no non-distinct aggregates (regardless of
    // whether there are group bys), there's no need to generate the
    // extra aggregate and join.
    final RelBuilder relBuilder = call.builder();
    relBuilder.push(aggregate.getInput());
    int n = 0;
    if (!newAggCallList.isEmpty()) {
        final RelBuilder.GroupKey groupKey = relBuilder.groupKey(groupSet, aggregate.indicator, aggregate.getGroupSets());
        relBuilder.aggregate(groupKey, newAggCallList);
        ++n;
    }
    // set of operands.
    for (Pair<List<Integer>, Integer> argList : argLists) {
        doRewrite(relBuilder, aggregate, n++, argList.left, argList.right, refs);
    }
    relBuilder.project(refs, fieldNames);
    call.transformTo(relBuilder.build());
}
Also used : LinkedHashSet(java.util.LinkedHashSet) RelBuilder(org.apache.calcite.tools.RelBuilder) SqlMinMaxAggFunction(org.apache.calcite.sql.fun.SqlMinMaxAggFunction) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) ArrayList(java.util.ArrayList) SqlCountAggFunction(org.apache.calcite.sql.fun.SqlCountAggFunction) AggregateCall(org.apache.calcite.rel.core.AggregateCall) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) SqlSumAggFunction(org.apache.calcite.sql.fun.SqlSumAggFunction) RexInputRef(org.apache.calcite.rex.RexInputRef) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) ImmutableIntList(org.apache.calcite.util.ImmutableIntList) List(java.util.List) Aggregate(org.apache.calcite.rel.core.Aggregate) LogicalAggregate(org.apache.calcite.rel.logical.LogicalAggregate) Pair(org.apache.calcite.util.Pair)

Example 2 with RelBuilder

use of org.apache.calcite.tools.RelBuilder in project hive by apache.

the class HiveSortLimitPullUpConstantsRule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    final RelNode parent = call.rel(0);
    final Sort sort = call.rel(1);
    final int count = sort.getInput().getRowType().getFieldCount();
    if (count == 1) {
        // Project operator.
        return;
    }
    final RexBuilder rexBuilder = sort.getCluster().getRexBuilder();
    final RelMetadataQuery mq = RelMetadataQuery.instance();
    final RelOptPredicateList predicates = mq.getPulledUpPredicates(sort.getInput());
    if (predicates == null) {
        return;
    }
    Map<RexNode, RexNode> conditionsExtracted = HiveReduceExpressionsRule.predicateConstants(RexNode.class, rexBuilder, predicates);
    Map<RexNode, RexNode> constants = new HashMap<>();
    for (int i = 0; i < count; i++) {
        RexNode expr = rexBuilder.makeInputRef(sort.getInput(), i);
        if (conditionsExtracted.containsKey(expr)) {
            constants.put(expr, conditionsExtracted.get(expr));
        }
    }
    // None of the expressions are constant. Nothing to do.
    if (constants.isEmpty()) {
        return;
    }
    if (count == constants.size()) {
        // At least a single item in project is required.
        constants.remove(constants.keySet().iterator().next());
    }
    // Create expressions for Project operators before and after the Sort
    List<RelDataTypeField> fields = sort.getInput().getRowType().getFieldList();
    List<Pair<RexNode, String>> newChildExprs = new ArrayList<>();
    List<RexNode> topChildExprs = new ArrayList<>();
    List<String> topChildExprsFields = new ArrayList<>();
    for (int i = 0; i < count; i++) {
        RexNode expr = rexBuilder.makeInputRef(sort.getInput(), i);
        RelDataTypeField field = fields.get(i);
        if (constants.containsKey(expr)) {
            topChildExprs.add(constants.get(expr));
            topChildExprsFields.add(field.getName());
        } else {
            newChildExprs.add(Pair.<RexNode, String>of(expr, field.getName()));
            topChildExprs.add(expr);
            topChildExprsFields.add(field.getName());
        }
    }
    // Update field collations
    final Mappings.TargetMapping mapping = RelOptUtil.permutation(Pair.left(newChildExprs), sort.getInput().getRowType()).inverse();
    List<RelFieldCollation> fieldCollations = new ArrayList<>();
    for (RelFieldCollation fc : sort.getCollation().getFieldCollations()) {
        final int target = mapping.getTargetOpt(fc.getFieldIndex());
        if (target < 0) {
            // It is a constant, we can ignore it
            continue;
        }
        fieldCollations.add(fc.copy(target));
    }
    // Update top Project positions
    topChildExprs = ImmutableList.copyOf(RexUtil.apply(mapping, topChildExprs));
    // Create new Project-Sort-Project sequence
    final RelBuilder relBuilder = call.builder();
    relBuilder.push(sort.getInput());
    relBuilder.project(Pair.left(newChildExprs), Pair.right(newChildExprs));
    final ImmutableList<RexNode> sortFields = relBuilder.fields(RelCollations.of(fieldCollations));
    relBuilder.sortLimit(sort.offset == null ? -1 : RexLiteral.intValue(sort.offset), sort.fetch == null ? -1 : RexLiteral.intValue(sort.fetch), sortFields);
    // Create top Project fixing nullability of fields
    relBuilder.project(topChildExprs, topChildExprsFields);
    relBuilder.convert(sort.getRowType(), false);
    List<RelNode> inputs = new ArrayList<>();
    for (RelNode child : parent.getInputs()) {
        if (!((HepRelVertex) child).getCurrentRel().equals(sort)) {
            inputs.add(child);
        } else {
            inputs.add(relBuilder.build());
        }
    }
    call.transformTo(parent.copy(parent.getTraitSet(), inputs));
}
Also used : RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) HepRelVertex(org.apache.calcite.plan.hep.HepRelVertex) RelOptPredicateList(org.apache.calcite.plan.RelOptPredicateList) Sort(org.apache.calcite.rel.core.Sort) RexBuilder(org.apache.calcite.rex.RexBuilder) Pair(org.apache.calcite.util.Pair) RelBuilder(org.apache.calcite.tools.RelBuilder) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) Mappings(org.apache.calcite.util.mapping.Mappings) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) RexNode(org.apache.calcite.rex.RexNode)

Example 3 with RelBuilder

use of org.apache.calcite.tools.RelBuilder in project hive by apache.

the class HiveUnionPullUpConstantsRule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    final Union union = call.rel(0);
    final int count = union.getRowType().getFieldCount();
    if (count == 1) {
        // Project operator.
        return;
    }
    final RexBuilder rexBuilder = union.getCluster().getRexBuilder();
    final RelMetadataQuery mq = RelMetadataQuery.instance();
    final RelOptPredicateList predicates = mq.getPulledUpPredicates(union);
    if (predicates == null) {
        return;
    }
    Map<RexNode, RexNode> conditionsExtracted = HiveReduceExpressionsRule.predicateConstants(RexNode.class, rexBuilder, predicates);
    Map<RexNode, RexNode> constants = new HashMap<>();
    for (int i = 0; i < count; i++) {
        RexNode expr = rexBuilder.makeInputRef(union, i);
        if (conditionsExtracted.containsKey(expr)) {
            constants.put(expr, conditionsExtracted.get(expr));
        }
    }
    // None of the expressions are constant. Nothing to do.
    if (constants.isEmpty()) {
        return;
    }
    // Create expressions for Project operators before and after the Union
    List<RelDataTypeField> fields = union.getRowType().getFieldList();
    List<RexNode> topChildExprs = new ArrayList<>();
    List<String> topChildExprsFields = new ArrayList<>();
    List<RexNode> refs = new ArrayList<>();
    ImmutableBitSet.Builder refsIndexBuilder = ImmutableBitSet.builder();
    for (int i = 0; i < count; i++) {
        RexNode expr = rexBuilder.makeInputRef(union, i);
        RelDataTypeField field = fields.get(i);
        if (constants.containsKey(expr)) {
            topChildExprs.add(constants.get(expr));
            topChildExprsFields.add(field.getName());
        } else {
            topChildExprs.add(expr);
            topChildExprsFields.add(field.getName());
            refs.add(expr);
            refsIndexBuilder.set(i);
        }
    }
    ImmutableBitSet refsIndex = refsIndexBuilder.build();
    // Update top Project positions
    final Mappings.TargetMapping mapping = RelOptUtil.permutation(refs, union.getInput(0).getRowType()).inverse();
    topChildExprs = ImmutableList.copyOf(RexUtil.apply(mapping, topChildExprs));
    // Create new Project-Union-Project sequences
    final RelBuilder relBuilder = call.builder();
    for (int i = 0; i < union.getInputs().size(); i++) {
        RelNode input = union.getInput(i);
        List<Pair<RexNode, String>> newChildExprs = new ArrayList<>();
        for (int j = 0; j < refsIndex.cardinality(); j++) {
            int pos = refsIndex.nth(j);
            newChildExprs.add(Pair.<RexNode, String>of(rexBuilder.makeInputRef(input, pos), input.getRowType().getFieldList().get(pos).getName()));
        }
        if (newChildExprs.isEmpty()) {
            // At least a single item in project is required.
            newChildExprs.add(Pair.<RexNode, String>of(topChildExprs.get(0), topChildExprsFields.get(0)));
        }
        // Add the input with project on top
        relBuilder.push(input);
        relBuilder.project(Pair.left(newChildExprs), Pair.right(newChildExprs));
    }
    relBuilder.union(union.all, union.getInputs().size());
    // Create top Project fixing nullability of fields
    relBuilder.project(topChildExprs, topChildExprsFields);
    relBuilder.convert(union.getRowType(), false);
    call.transformTo(relBuilder.build());
}
Also used : RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) RelBuilder(org.apache.calcite.tools.RelBuilder) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) HiveUnion(org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveUnion) Union(org.apache.calcite.rel.core.Union) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) Mappings(org.apache.calcite.util.mapping.Mappings) RelNode(org.apache.calcite.rel.RelNode) RelOptPredicateList(org.apache.calcite.plan.RelOptPredicateList) RexBuilder(org.apache.calcite.rex.RexBuilder) RexNode(org.apache.calcite.rex.RexNode) Pair(org.apache.calcite.util.Pair)

Example 4 with RelBuilder

use of org.apache.calcite.tools.RelBuilder in project hive by apache.

the class HiveProjectFilterPullUpConstantsRule method onMatch.

public void onMatch(RelOptRuleCall call) {
    final Project project = call.rel(0);
    final Filter filter = call.rel(1);
    final RelBuilder builder = call.builder();
    List<RexNode> projects = project.getChildExps();
    List<RexNode> newProjects = rewriteProjects(projects, filter.getCondition(), builder);
    if (newProjects == null) {
        return;
    }
    RelNode newProjRel = builder.push(filter).project(newProjects, project.getRowType().getFieldNames()).build();
    call.transformTo(newProjRel);
}
Also used : Project(org.apache.calcite.rel.core.Project) HiveProject(org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveProject) RelBuilder(org.apache.calcite.tools.RelBuilder) RelNode(org.apache.calcite.rel.RelNode) Filter(org.apache.calcite.rel.core.Filter) HiveFilter(org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveFilter) RexNode(org.apache.calcite.rex.RexNode)

Example 5 with RelBuilder

use of org.apache.calcite.tools.RelBuilder 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

RelBuilder (org.apache.calcite.tools.RelBuilder)7 ArrayList (java.util.ArrayList)6 RelNode (org.apache.calcite.rel.RelNode)5 RexNode (org.apache.calcite.rex.RexNode)5 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)5 HashMap (java.util.HashMap)4 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)4 RexBuilder (org.apache.calcite.rex.RexBuilder)4 Pair (org.apache.calcite.util.Pair)4 AggregateCall (org.apache.calcite.rel.core.AggregateCall)3 RelMetadataQuery (org.apache.calcite.rel.metadata.RelMetadataQuery)3 Mappings (org.apache.calcite.util.mapping.Mappings)3 ImmutableList (com.google.common.collect.ImmutableList)2 List (java.util.List)2 RelOptPredicateList (org.apache.calcite.plan.RelOptPredicateList)2 Aggregate (org.apache.calcite.rel.core.Aggregate)2 Join (org.apache.calcite.rel.core.Join)2 Project (org.apache.calcite.rel.core.Project)2 LogicalAggregate (org.apache.calcite.rel.logical.LogicalAggregate)2 RexInputRef (org.apache.calcite.rex.RexInputRef)2