Search in sources :

Example 1 with Grouping

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

the class GroupByRules method applyLimit.

/**
   * Applies a sort to an aggregating druidRel, as a LimitSpec. Do not call this method unless
   * {@link #canApplyLimit(DruidRel)} returns true.
   *
   * @return new rel, or null if the sort cannot be applied
   */
private static DruidRel applyLimit(final DruidRel druidRel, final Sort sort) {
    Preconditions.checkState(canApplyLimit(druidRel), "Cannot applyLimit.");
    final Grouping grouping = druidRel.getQueryBuilder().getGrouping();
    final DefaultLimitSpec limitSpec = toLimitSpec(druidRel.getQueryBuilder().getRowOrder(), sort);
    if (limitSpec == null) {
        return null;
    }
    final List<OrderByColumnSpec> orderBys = limitSpec.getColumns();
    final List<DimensionSpec> newDimensions = Lists.newArrayList(grouping.getDimensions());
    // Reorder dimensions, maybe, to allow groupBy to consider pushing down sorting (see DefaultLimitSpec).
    if (!orderBys.isEmpty()) {
        final Map<String, Integer> dimensionOrderByOutputName = Maps.newHashMap();
        for (int i = 0; i < newDimensions.size(); i++) {
            dimensionOrderByOutputName.put(newDimensions.get(i).getOutputName(), i);
        }
        for (int i = 0; i < orderBys.size(); i++) {
            final OrderByColumnSpec orderBy = orderBys.get(i);
            final Integer dimensionOrder = dimensionOrderByOutputName.get(orderBy.getDimension());
            if (dimensionOrder != null && dimensionOrder != i && orderBy.getDirection() == OrderByColumnSpec.Direction.ASCENDING && orderBy.getDimensionComparator().equals(StringComparators.LEXICOGRAPHIC)) {
                final DimensionSpec tmp = newDimensions.get(i);
                newDimensions.set(i, newDimensions.get(dimensionOrder));
                newDimensions.set(dimensionOrder, tmp);
                dimensionOrderByOutputName.put(newDimensions.get(i).getOutputName(), i);
                dimensionOrderByOutputName.put(newDimensions.get(dimensionOrder).getOutputName(), dimensionOrder);
            }
        }
    }
    if (!orderBys.isEmpty() || limitSpec.getLimit() < Integer.MAX_VALUE) {
        return druidRel.withQueryBuilder(druidRel.getQueryBuilder().withAdjustedGrouping(Grouping.create(newDimensions, grouping.getAggregations()), druidRel.getQueryBuilder().getRowType(), druidRel.getQueryBuilder().getRowOrder()).withLimitSpec(limitSpec));
    } else {
        return druidRel;
    }
}
Also used : OrderByColumnSpec(io.druid.query.groupby.orderby.OrderByColumnSpec) DimensionSpec(io.druid.query.dimension.DimensionSpec) DefaultLimitSpec(io.druid.query.groupby.orderby.DefaultLimitSpec) Grouping(io.druid.sql.calcite.rel.Grouping)

Example 2 with Grouping

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

the class GroupByRules method applyPostAggregation.

/**
   * Applies a projection to the aggregations of a druidRel, by potentially adding post-aggregators.
   *
   * @return new rel, or null if the projection cannot be applied
   */
private static DruidRel applyPostAggregation(final DruidRel druidRel, final Project postProject) {
    Preconditions.checkState(canApplyPostAggregation(druidRel), "Cannot applyPostAggregation");
    final List<String> rowOrder = druidRel.getQueryBuilder().getRowOrder();
    final Grouping grouping = druidRel.getQueryBuilder().getGrouping();
    final List<Aggregation> newAggregations = Lists.newArrayList(grouping.getAggregations());
    final List<PostAggregatorFactory> finalizingPostAggregatorFactories = Lists.newArrayList();
    final List<String> newRowOrder = Lists.newArrayList();
    // Build list of finalizingPostAggregatorFactories.
    final Map<String, Aggregation> aggregationMap = Maps.newHashMap();
    for (final Aggregation aggregation : grouping.getAggregations()) {
        aggregationMap.put(aggregation.getOutputName(), aggregation);
    }
    for (final String field : rowOrder) {
        final Aggregation aggregation = aggregationMap.get(field);
        finalizingPostAggregatorFactories.add(aggregation == null ? null : aggregation.getFinalizingPostAggregatorFactory());
    }
    // Walk through the postProject expressions.
    for (final RexNode projectExpression : postProject.getChildExps()) {
        if (projectExpression.isA(SqlKind.INPUT_REF)) {
            final RexInputRef ref = (RexInputRef) projectExpression;
            final String fieldName = rowOrder.get(ref.getIndex());
            newRowOrder.add(fieldName);
            finalizingPostAggregatorFactories.add(null);
        } else {
            // Attempt to convert to PostAggregator.
            final String postAggregatorName = aggOutputName(newAggregations.size());
            final PostAggregator postAggregator = Expressions.toPostAggregator(postAggregatorName, rowOrder, finalizingPostAggregatorFactories, projectExpression);
            if (postAggregator != null) {
                newAggregations.add(Aggregation.create(postAggregator));
                newRowOrder.add(postAggregator.getName());
                finalizingPostAggregatorFactories.add(null);
            } else {
                return null;
            }
        }
    }
    return druidRel.withQueryBuilder(druidRel.getQueryBuilder().withAdjustedGrouping(Grouping.create(grouping.getDimensions(), newAggregations), postProject.getRowType(), newRowOrder));
}
Also used : Aggregation(io.druid.sql.calcite.aggregation.Aggregation) PostAggregator(io.druid.query.aggregation.PostAggregator) FieldAccessPostAggregator(io.druid.query.aggregation.post.FieldAccessPostAggregator) ArithmeticPostAggregator(io.druid.query.aggregation.post.ArithmeticPostAggregator) RexInputRef(org.apache.calcite.rex.RexInputRef) Grouping(io.druid.sql.calcite.rel.Grouping) PostAggregatorFactory(io.druid.sql.calcite.aggregation.PostAggregatorFactory) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

Grouping (io.druid.sql.calcite.rel.Grouping)2 PostAggregator (io.druid.query.aggregation.PostAggregator)1 ArithmeticPostAggregator (io.druid.query.aggregation.post.ArithmeticPostAggregator)1 FieldAccessPostAggregator (io.druid.query.aggregation.post.FieldAccessPostAggregator)1 DimensionSpec (io.druid.query.dimension.DimensionSpec)1 DefaultLimitSpec (io.druid.query.groupby.orderby.DefaultLimitSpec)1 OrderByColumnSpec (io.druid.query.groupby.orderby.OrderByColumnSpec)1 Aggregation (io.druid.sql.calcite.aggregation.Aggregation)1 PostAggregatorFactory (io.druid.sql.calcite.aggregation.PostAggregatorFactory)1 RexInputRef (org.apache.calcite.rex.RexInputRef)1 RexNode (org.apache.calcite.rex.RexNode)1