Search in sources :

Example 1 with RowExtraction

use of io.druid.sql.calcite.expression.RowExtraction in project druid by druid-io.

the class QuantileSqlAggregator method toDruidAggregation.

@Override
public Aggregation toDruidAggregation(final String name, final RowSignature rowSignature, final DruidOperatorTable operatorTable, final PlannerContext plannerContext, final List<Aggregation> existingAggregations, final Project project, final AggregateCall aggregateCall, final DimFilter filter) {
    final RowExtraction rex = Expressions.toRowExtraction(operatorTable, plannerContext, rowSignature.getRowOrder(), Expressions.fromFieldAccess(rowSignature, project, aggregateCall.getArgList().get(0)));
    if (rex == null) {
        return null;
    }
    final AggregatorFactory aggregatorFactory;
    final String histogramName = String.format("%s:agg", name);
    final RexNode probabilityArg = Expressions.fromFieldAccess(rowSignature, project, aggregateCall.getArgList().get(1));
    final float probability = ((Number) RexLiteral.value(probabilityArg)).floatValue();
    final int resolution;
    if (aggregateCall.getArgList().size() >= 3) {
        final RexNode resolutionArg = Expressions.fromFieldAccess(rowSignature, project, aggregateCall.getArgList().get(2));
        resolution = ((Number) RexLiteral.value(resolutionArg)).intValue();
    } else {
        resolution = ApproximateHistogram.DEFAULT_HISTOGRAM_SIZE;
    }
    final int numBuckets = ApproximateHistogram.DEFAULT_BUCKET_SIZE;
    final float lowerLimit = Float.NEGATIVE_INFINITY;
    final float upperLimit = Float.POSITIVE_INFINITY;
    // Look for existing matching aggregatorFactory.
    for (final Aggregation existing : existingAggregations) {
        for (AggregatorFactory factory : existing.getAggregatorFactories()) {
            final boolean matches = Aggregations.aggregatorMatches(factory, filter, ApproximateHistogramAggregatorFactory.class, new Predicate<ApproximateHistogramAggregatorFactory>() {

                @Override
                public boolean apply(final ApproximateHistogramAggregatorFactory theFactory) {
                    return theFactory.getFieldName().equals(rex.getColumn()) && theFactory.getResolution() == resolution && theFactory.getNumBuckets() == numBuckets && theFactory.getLowerLimit() == lowerLimit && theFactory.getUpperLimit() == upperLimit;
                }
            });
            if (matches) {
                // Found existing one. Use this.
                return Aggregation.create(ImmutableList.<AggregatorFactory>of(), new QuantilePostAggregator(name, factory.getName(), probability));
            }
        }
    }
    if (rowSignature.getColumnType(rex.getColumn()) == ValueType.COMPLEX) {
        aggregatorFactory = new ApproximateHistogramFoldingAggregatorFactory(histogramName, rex.getColumn(), resolution, numBuckets, lowerLimit, upperLimit);
    } else {
        aggregatorFactory = new ApproximateHistogramAggregatorFactory(histogramName, rex.getColumn(), resolution, numBuckets, lowerLimit, upperLimit);
    }
    return Aggregation.create(ImmutableList.of(aggregatorFactory), new QuantilePostAggregator(name, histogramName, probability)).filter(filter);
}
Also used : ApproximateHistogramFoldingAggregatorFactory(io.druid.query.aggregation.histogram.ApproximateHistogramFoldingAggregatorFactory) QuantilePostAggregator(io.druid.query.aggregation.histogram.QuantilePostAggregator) RowExtraction(io.druid.sql.calcite.expression.RowExtraction) AggregatorFactory(io.druid.query.aggregation.AggregatorFactory) ApproximateHistogramFoldingAggregatorFactory(io.druid.query.aggregation.histogram.ApproximateHistogramFoldingAggregatorFactory) ApproximateHistogramAggregatorFactory(io.druid.query.aggregation.histogram.ApproximateHistogramAggregatorFactory) Aggregation(io.druid.sql.calcite.aggregation.Aggregation) ApproximateHistogramAggregatorFactory(io.druid.query.aggregation.histogram.ApproximateHistogramAggregatorFactory) RexNode(org.apache.calcite.rex.RexNode)

Example 2 with RowExtraction

use of io.druid.sql.calcite.expression.RowExtraction in project druid by druid-io.

the class ApproxCountDistinctSqlAggregator method toDruidAggregation.

@Override
public Aggregation toDruidAggregation(final String name, final RowSignature rowSignature, final DruidOperatorTable operatorTable, final PlannerContext plannerContext, final List<Aggregation> existingAggregations, final Project project, final AggregateCall aggregateCall, final DimFilter filter) {
    final RexNode rexNode = Expressions.fromFieldAccess(rowSignature, project, Iterables.getOnlyElement(aggregateCall.getArgList()));
    final RowExtraction rex = Expressions.toRowExtraction(operatorTable, plannerContext, rowSignature.getRowOrder(), rexNode);
    if (rex == null) {
        return null;
    }
    final AggregatorFactory aggregatorFactory;
    if (rowSignature.getColumnType(rex.getColumn()) == ValueType.COMPLEX) {
        aggregatorFactory = new HyperUniquesAggregatorFactory(name, rex.getColumn());
    } else {
        final SqlTypeName sqlTypeName = rexNode.getType().getSqlTypeName();
        final ValueType outputType = Calcites.getValueTypeForSqlTypeName(sqlTypeName);
        if (outputType == null) {
            throw new ISE("Cannot translate sqlTypeName[%s] to Druid type for field[%s]", sqlTypeName, name);
        }
        final DimensionSpec dimensionSpec = rex.toDimensionSpec(rowSignature, null, ValueType.STRING);
        if (dimensionSpec == null) {
            return null;
        }
        aggregatorFactory = new CardinalityAggregatorFactory(name, ImmutableList.of(dimensionSpec), false);
    }
    return Aggregation.createFinalizable(ImmutableList.<AggregatorFactory>of(aggregatorFactory), null, new PostAggregatorFactory() {

        @Override
        public PostAggregator factorize(String outputName) {
            return new HyperUniqueFinalizingPostAggregator(outputName, name);
        }
    }).filter(filter);
}
Also used : DimensionSpec(io.druid.query.dimension.DimensionSpec) SqlTypeName(org.apache.calcite.sql.type.SqlTypeName) ValueType(io.druid.segment.column.ValueType) HyperUniquesAggregatorFactory(io.druid.query.aggregation.hyperloglog.HyperUniquesAggregatorFactory) RowExtraction(io.druid.sql.calcite.expression.RowExtraction) ISE(io.druid.java.util.common.ISE) HyperUniqueFinalizingPostAggregator(io.druid.query.aggregation.hyperloglog.HyperUniqueFinalizingPostAggregator) AggregatorFactory(io.druid.query.aggregation.AggregatorFactory) HyperUniquesAggregatorFactory(io.druid.query.aggregation.hyperloglog.HyperUniquesAggregatorFactory) CardinalityAggregatorFactory(io.druid.query.aggregation.cardinality.CardinalityAggregatorFactory) CardinalityAggregatorFactory(io.druid.query.aggregation.cardinality.CardinalityAggregatorFactory) RexNode(org.apache.calcite.rex.RexNode)

Example 3 with RowExtraction

use of io.druid.sql.calcite.expression.RowExtraction in project druid by druid-io.

the class DruidSemiJoin method from.

public static DruidSemiJoin from(final DruidRel left, final DruidRel right, final List<Integer> leftKeys, final List<Integer> rightKeys, final PlannerConfig plannerConfig) {
    final ImmutableList.Builder<RowExtraction> listBuilder = ImmutableList.builder();
    for (Integer key : leftKeys) {
        final RowExtraction rex = RowExtraction.fromQueryBuilder(left.getQueryBuilder(), key);
        if (rex == null) {
            // Can't figure out what to filter the left-hand side on...
            return null;
        }
        listBuilder.add(rex);
    }
    return new DruidSemiJoin(left.getCluster(), left.getTraitSet(), left, right, listBuilder.build(), rightKeys, plannerConfig.getMaxSemiJoinRowsInMemory());
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) RowExtraction(io.druid.sql.calcite.expression.RowExtraction)

Example 4 with RowExtraction

use of io.druid.sql.calcite.expression.RowExtraction in project druid by druid-io.

the class GroupByRules method applyAggregate.

/**
   * Applies a filter -> project -> aggregate chain to a druidRel. Do not call this method unless
   * {@link #canApplyAggregate(DruidRel, Filter, Project, Aggregate)} returns true.
   *
   * @return new rel, or null if the chain cannot be applied
   */
private static DruidRel applyAggregate(final DruidRel druidRel, final Filter filter0, final Project project0, final Aggregate aggregate, final DruidOperatorTable operatorTable, final boolean approximateCountDistinct) {
    Preconditions.checkState(canApplyAggregate(druidRel, filter0, project0, aggregate), "Cannot applyAggregate.");
    final RowSignature sourceRowSignature;
    final boolean isNestedQuery = druidRel.getQueryBuilder().getGrouping() != null;
    if (isNestedQuery) {
        // Nested groupBy; source row signature is the output signature of druidRel.
        sourceRowSignature = druidRel.getOutputRowSignature();
    } else {
        sourceRowSignature = druidRel.getSourceRowSignature();
    }
    // Filter that should be applied before aggregating.
    final DimFilter filter;
    if (filter0 != null) {
        filter = Expressions.toFilter(operatorTable, druidRel.getPlannerContext(), sourceRowSignature, filter0.getCondition());
        if (filter == null) {
            // Can't plan this filter.
            return null;
        }
    } else if (druidRel.getQueryBuilder().getFilter() != null && !isNestedQuery) {
        // We're going to replace the existing druidRel, so inherit its filter.
        filter = druidRel.getQueryBuilder().getFilter();
    } else {
        filter = null;
    }
    // Projection that should be applied before aggregating.
    final Project project;
    if (project0 != null) {
        project = project0;
    } else if (druidRel.getQueryBuilder().getSelectProjection() != null && !isNestedQuery) {
        // We're going to replace the existing druidRel, so inherit its projection.
        project = druidRel.getQueryBuilder().getSelectProjection().getProject();
    } else {
        project = null;
    }
    final List<DimensionSpec> dimensions = Lists.newArrayList();
    final List<Aggregation> aggregations = Lists.newArrayList();
    final List<String> rowOrder = Lists.newArrayList();
    // Translate groupSet.
    final ImmutableBitSet groupSet = aggregate.getGroupSet();
    int dimOutputNameCounter = 0;
    for (int i : groupSet) {
        if (project != null && project.getChildExps().get(i) instanceof RexLiteral) {
            // Ignore literals in GROUP BY, so a user can write e.g. "GROUP BY 'dummy'" to group everything into a single
            // row. Add dummy rowOrder entry so NULLs come out. This is not strictly correct but it works as long as
            // nobody actually expects to see the literal.
            rowOrder.add(dimOutputName(dimOutputNameCounter++));
        } else {
            final RexNode rexNode = Expressions.fromFieldAccess(sourceRowSignature, project, i);
            final RowExtraction rex = Expressions.toRowExtraction(operatorTable, druidRel.getPlannerContext(), sourceRowSignature.getRowOrder(), rexNode);
            if (rex == null) {
                return null;
            }
            final SqlTypeName sqlTypeName = rexNode.getType().getSqlTypeName();
            final ValueType outputType = Calcites.getValueTypeForSqlTypeName(sqlTypeName);
            if (outputType == null) {
                throw new ISE("Cannot translate sqlTypeName[%s] to Druid type for field[%s]", sqlTypeName, rowOrder.get(i));
            }
            final DimensionSpec dimensionSpec = rex.toDimensionSpec(sourceRowSignature, dimOutputName(dimOutputNameCounter++), outputType);
            if (dimensionSpec == null) {
                return null;
            }
            dimensions.add(dimensionSpec);
            rowOrder.add(dimensionSpec.getOutputName());
        }
    }
    // Translate aggregates.
    for (int i = 0; i < aggregate.getAggCallList().size(); i++) {
        final AggregateCall aggCall = aggregate.getAggCallList().get(i);
        final Aggregation aggregation = translateAggregateCall(druidRel.getPlannerContext(), sourceRowSignature, project, aggCall, operatorTable, aggregations, i, approximateCountDistinct);
        if (aggregation == null) {
            return null;
        }
        aggregations.add(aggregation);
        rowOrder.add(aggregation.getOutputName());
    }
    if (isNestedQuery) {
        // Nested groupBy.
        return DruidNestedGroupBy.from(druidRel, filter, Grouping.create(dimensions, aggregations), aggregate.getRowType(), rowOrder);
    } else {
        // groupBy on a base dataSource.
        return druidRel.withQueryBuilder(druidRel.getQueryBuilder().withFilter(filter).withGrouping(Grouping.create(dimensions, aggregations), aggregate.getRowType(), rowOrder));
    }
}
Also used : DimensionSpec(io.druid.query.dimension.DimensionSpec) RexLiteral(org.apache.calcite.rex.RexLiteral) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) SqlTypeName(org.apache.calcite.sql.type.SqlTypeName) ValueType(io.druid.segment.column.ValueType) RowExtraction(io.druid.sql.calcite.expression.RowExtraction) Aggregation(io.druid.sql.calcite.aggregation.Aggregation) AggregateCall(org.apache.calcite.rel.core.AggregateCall) Project(org.apache.calcite.rel.core.Project) ISE(io.druid.java.util.common.ISE) RowSignature(io.druid.sql.calcite.table.RowSignature) DimFilter(io.druid.query.filter.DimFilter) NotDimFilter(io.druid.query.filter.NotDimFilter) AndDimFilter(io.druid.query.filter.AndDimFilter) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

RowExtraction (io.druid.sql.calcite.expression.RowExtraction)4 RexNode (org.apache.calcite.rex.RexNode)3 ISE (io.druid.java.util.common.ISE)2 AggregatorFactory (io.druid.query.aggregation.AggregatorFactory)2 DimensionSpec (io.druid.query.dimension.DimensionSpec)2 ValueType (io.druid.segment.column.ValueType)2 Aggregation (io.druid.sql.calcite.aggregation.Aggregation)2 SqlTypeName (org.apache.calcite.sql.type.SqlTypeName)2 ImmutableList (com.google.common.collect.ImmutableList)1 CardinalityAggregatorFactory (io.druid.query.aggregation.cardinality.CardinalityAggregatorFactory)1 ApproximateHistogramAggregatorFactory (io.druid.query.aggregation.histogram.ApproximateHistogramAggregatorFactory)1 ApproximateHistogramFoldingAggregatorFactory (io.druid.query.aggregation.histogram.ApproximateHistogramFoldingAggregatorFactory)1 QuantilePostAggregator (io.druid.query.aggregation.histogram.QuantilePostAggregator)1 HyperUniqueFinalizingPostAggregator (io.druid.query.aggregation.hyperloglog.HyperUniqueFinalizingPostAggregator)1 HyperUniquesAggregatorFactory (io.druid.query.aggregation.hyperloglog.HyperUniquesAggregatorFactory)1 AndDimFilter (io.druid.query.filter.AndDimFilter)1 DimFilter (io.druid.query.filter.DimFilter)1 NotDimFilter (io.druid.query.filter.NotDimFilter)1 RowSignature (io.druid.sql.calcite.table.RowSignature)1 AggregateCall (org.apache.calcite.rel.core.AggregateCall)1