Search in sources :

Example 51 with OrderByColumnSpec

use of org.apache.druid.query.groupby.orderby.OrderByColumnSpec in project druid by druid-io.

the class GroupByQueryRunnerTest method testGroupByLimitPushDownPostAggNotSupported.

@Test
public void testGroupByLimitPushDownPostAggNotSupported() {
    if (!config.getDefaultStrategy().equals(GroupByStrategySelector.STRATEGY_V2)) {
        return;
    }
    expectedException.expect(UnsupportedOperationException.class);
    expectedException.expectMessage("Limit push down when sorting by a post aggregator is not supported.");
    GroupByQuery query = makeQueryBuilder().setDataSource(QueryRunnerTestHelper.DATA_SOURCE).setGranularity(QueryRunnerTestHelper.ALL_GRAN).setDimensions(new DefaultDimensionSpec(QueryRunnerTestHelper.MARKET_DIMENSION, "marketalias")).setInterval(QueryRunnerTestHelper.FULL_ON_INTERVAL_SPEC).setLimitSpec(new DefaultLimitSpec(Collections.singletonList(new OrderByColumnSpec("constant", OrderByColumnSpec.Direction.DESCENDING)), 2)).setAggregatorSpecs(QueryRunnerTestHelper.ROWS_COUNT).setPostAggregatorSpecs(Collections.singletonList(new ConstantPostAggregator("constant", 1))).overrideContext(ImmutableMap.of(GroupByQueryConfig.CTX_KEY_FORCE_LIMIT_PUSH_DOWN, true)).build();
    GroupByQueryRunnerTestHelper.runQuery(factory, runner, query);
}
Also used : OrderByColumnSpec(org.apache.druid.query.groupby.orderby.OrderByColumnSpec) DefaultLimitSpec(org.apache.druid.query.groupby.orderby.DefaultLimitSpec) ConstantPostAggregator(org.apache.druid.query.aggregation.post.ConstantPostAggregator) DefaultDimensionSpec(org.apache.druid.query.dimension.DefaultDimensionSpec) InitializedNullHandlingTest(org.apache.druid.testing.InitializedNullHandlingTest) Test(org.junit.Test)

Example 52 with OrderByColumnSpec

use of org.apache.druid.query.groupby.orderby.OrderByColumnSpec in project druid by druid-io.

the class GroupByQueryRunnerTest method testGroupByWithHavingOnHyperUnique.

@Test
public void testGroupByWithHavingOnHyperUnique() {
    GroupByQuery query = makeQueryBuilder().setDataSource(QueryRunnerTestHelper.DATA_SOURCE).setGranularity(QueryRunnerTestHelper.ALL_GRAN).setDimensions(new DefaultDimensionSpec(QueryRunnerTestHelper.MARKET_DIMENSION, QueryRunnerTestHelper.MARKET_DIMENSION)).setInterval(QueryRunnerTestHelper.FULL_ON_INTERVAL_SPEC).setLimitSpec(new DefaultLimitSpec(Collections.singletonList(new OrderByColumnSpec(QueryRunnerTestHelper.UNIQUE_METRIC, OrderByColumnSpec.Direction.DESCENDING)), 3)).setHavingSpec(new GreaterThanHavingSpec(QueryRunnerTestHelper.UNIQUE_METRIC, 8)).setAggregatorSpecs(QueryRunnerTestHelper.QUALITY_UNIQUES).setPostAggregatorSpecs(Collections.singletonList(new HyperUniqueFinalizingPostAggregator(QueryRunnerTestHelper.HYPER_UNIQUE_FINALIZING_POST_AGG_METRIC, QueryRunnerTestHelper.UNIQUE_METRIC))).build();
    List<ResultRow> expectedResults = Collections.singletonList(makeRow(query, "1970-01-01T00:00:00.000Z", "market", "spot", QueryRunnerTestHelper.UNIQUE_METRIC, QueryRunnerTestHelper.UNIQUES_9, QueryRunnerTestHelper.HYPER_UNIQUE_FINALIZING_POST_AGG_METRIC, QueryRunnerTestHelper.UNIQUES_9));
    Iterable<ResultRow> results = GroupByQueryRunnerTestHelper.runQuery(factory, runner, query);
    TestHelper.assertExpectedObjects(expectedResults, results, "order-limit");
}
Also used : OrderByColumnSpec(org.apache.druid.query.groupby.orderby.OrderByColumnSpec) DefaultLimitSpec(org.apache.druid.query.groupby.orderby.DefaultLimitSpec) GreaterThanHavingSpec(org.apache.druid.query.groupby.having.GreaterThanHavingSpec) HyperUniqueFinalizingPostAggregator(org.apache.druid.query.aggregation.hyperloglog.HyperUniqueFinalizingPostAggregator) DefaultDimensionSpec(org.apache.druid.query.dimension.DefaultDimensionSpec) InitializedNullHandlingTest(org.apache.druid.testing.InitializedNullHandlingTest) Test(org.junit.Test)

Example 53 with OrderByColumnSpec

use of org.apache.druid.query.groupby.orderby.OrderByColumnSpec in project druid by druid-io.

the class GroupByQueryRunnerTest method testMultiValueDimensionAsArrayWithOtherDims.

@Test
public void testMultiValueDimensionAsArrayWithOtherDims() {
    // array types don't work with group by v1
    if (config.getDefaultStrategy().equals(GroupByStrategySelector.STRATEGY_V1)) {
        expectedException.expect(UnsupportedOperationException.class);
        expectedException.expectMessage("GroupBy v1 only supports dimensions with an outputType of STRING");
    }
    // Cannot vectorize due to multi-value dimensions.
    cannotVectorize();
    GroupByQuery query = makeQueryBuilder().setDataSource(QueryRunnerTestHelper.DATA_SOURCE).setQuerySegmentSpec(QueryRunnerTestHelper.FIRST_TO_THIRD).setVirtualColumns(new ExpressionVirtualColumn("v0", "mv_to_array(placementish)", ColumnType.STRING_ARRAY, ExprMacroTable.nil())).setDimensions(new DefaultDimensionSpec("v0", "alias", ColumnType.STRING_ARRAY), new DefaultDimensionSpec("quality", "quality")).setLimitSpec(new DefaultLimitSpec(ImmutableList.of(new OrderByColumnSpec("alias", OrderByColumnSpec.Direction.ASCENDING, StringComparators.LEXICOGRAPHIC), new OrderByColumnSpec("quality", OrderByColumnSpec.Direction.ASCENDING, StringComparators.LEXICOGRAPHIC)), Integer.MAX_VALUE - 1)).setAggregatorSpecs(QueryRunnerTestHelper.ROWS_COUNT, new LongSumAggregatorFactory("idx", "index")).setGranularity(QueryRunnerTestHelper.ALL_GRAN).build();
    List<ResultRow> expectedResults = Arrays.asList(makeRow(query, "2011-04-01", "alias", ComparableStringArray.of("a", "preferred"), "quality", "automotive", "rows", 2L, "idx", 282L), makeRow(query, "2011-04-01", "alias", ComparableStringArray.of("b", "preferred"), "quality", "business", "rows", 2L, "idx", 230L), makeRow(query, "2011-04-01", "alias", ComparableStringArray.of("e", "preferred"), "quality", "entertainment", "rows", 2L, "idx", 324L), makeRow(query, "2011-04-01", "alias", ComparableStringArray.of("h", "preferred"), "quality", "health", "rows", 2L, "idx", 233L), makeRow(query, "2011-04-01", "alias", ComparableStringArray.of("m", "preferred"), "quality", "mezzanine", "rows", 6L, "idx", 5317L), makeRow(query, "2011-04-01", "alias", ComparableStringArray.of("n", "preferred"), "quality", "news", "rows", 2L, "idx", 235L), makeRow(query, "2011-04-01", "alias", ComparableStringArray.of("p", "preferred"), "quality", "premium", "rows", 6L, "idx", 5405L), makeRow(query, "2011-04-01", "alias", ComparableStringArray.of("preferred", "t"), "quality", "technology", "rows", 2L, "idx", 175L), makeRow(query, "2011-04-01", "alias", ComparableStringArray.of("preferred", "t"), "quality", "travel", "rows", 2L, "idx", 245L));
    Iterable<ResultRow> results = GroupByQueryRunnerTestHelper.runQuery(factory, runner, query);
    TestHelper.assertExpectedObjects(expectedResults, results, "multi-value-dims-groupby-arrays");
    query = makeQueryBuilder().setDataSource(QueryRunnerTestHelper.DATA_SOURCE).setQuerySegmentSpec(QueryRunnerTestHelper.FIRST_TO_THIRD).setVirtualColumns(new ExpressionVirtualColumn("v0", "mv_to_array(placementish)", ColumnType.STRING_ARRAY, ExprMacroTable.nil())).setDimensions(new DefaultDimensionSpec("v0", "alias", ColumnType.STRING_ARRAY), new DefaultDimensionSpec("quality", "quality")).setLimitSpec(new DefaultLimitSpec(ImmutableList.of(new OrderByColumnSpec("alias", OrderByColumnSpec.Direction.DESCENDING, StringComparators.LEXICOGRAPHIC), new OrderByColumnSpec("quality", OrderByColumnSpec.Direction.DESCENDING, StringComparators.LEXICOGRAPHIC)), Integer.MAX_VALUE - 1)).setAggregatorSpecs(QueryRunnerTestHelper.ROWS_COUNT, new LongSumAggregatorFactory("idx", "index")).setGranularity(QueryRunnerTestHelper.ALL_GRAN).build();
    Collections.reverse(expectedResults);
    results = GroupByQueryRunnerTestHelper.runQuery(factory, runner, query);
    TestHelper.assertExpectedObjects(expectedResults, results, "multi-value-dims-groupby-arrays-descending");
}
Also used : OrderByColumnSpec(org.apache.druid.query.groupby.orderby.OrderByColumnSpec) ExpressionVirtualColumn(org.apache.druid.segment.virtual.ExpressionVirtualColumn) DefaultLimitSpec(org.apache.druid.query.groupby.orderby.DefaultLimitSpec) LongSumAggregatorFactory(org.apache.druid.query.aggregation.LongSumAggregatorFactory) DefaultDimensionSpec(org.apache.druid.query.dimension.DefaultDimensionSpec) InitializedNullHandlingTest(org.apache.druid.testing.InitializedNullHandlingTest) Test(org.junit.Test)

Example 54 with OrderByColumnSpec

use of org.apache.druid.query.groupby.orderby.OrderByColumnSpec in project druid by druid-io.

the class DruidQuery method toTopNQuery.

/**
 * Return this query as a TopN query, or null if this query is not compatible with TopN.
 *
 * @return query or null
 */
@Nullable
private TopNQuery toTopNQuery(final QueryFeatureInspector queryFeatureInspector) {
    // Must be allowed by the QueryMaker.
    if (!queryFeatureInspector.feature(QueryFeature.CAN_RUN_TOPN)) {
        return null;
    }
    // Must have GROUP BY one column, no GROUPING SETS, ORDER BY ≤ 1 column, LIMIT > 0 and ≤ maxTopNLimit,
    // no OFFSET, no HAVING.
    final boolean topNOk = grouping != null && grouping.getDimensions().size() == 1 && !grouping.getSubtotals().hasEffect(grouping.getDimensionSpecs()) && sorting != null && (sorting.getOrderBys().size() <= 1 && sorting.getOffsetLimit().hasLimit() && sorting.getOffsetLimit().getLimit() > 0 && sorting.getOffsetLimit().getLimit() <= plannerContext.getPlannerConfig().getMaxTopNLimit() && !sorting.getOffsetLimit().hasOffset()) && grouping.getHavingFilter() == null;
    if (!topNOk) {
        return null;
    }
    final DimensionSpec dimensionSpec = Iterables.getOnlyElement(grouping.getDimensions()).toDimensionSpec();
    // grouping col cannot be type array
    if (dimensionSpec.getOutputType().isArray()) {
        return null;
    }
    final OrderByColumnSpec limitColumn;
    if (sorting.getOrderBys().isEmpty()) {
        limitColumn = new OrderByColumnSpec(dimensionSpec.getOutputName(), OrderByColumnSpec.Direction.ASCENDING, Calcites.getStringComparatorForValueType(dimensionSpec.getOutputType()));
    } else {
        limitColumn = Iterables.getOnlyElement(sorting.getOrderBys());
    }
    final TopNMetricSpec topNMetricSpec;
    if (limitColumn.getDimension().equals(dimensionSpec.getOutputName())) {
        // DimensionTopNMetricSpec is exact; always return it even if allowApproximate is false.
        final DimensionTopNMetricSpec baseMetricSpec = new DimensionTopNMetricSpec(null, limitColumn.getDimensionComparator());
        topNMetricSpec = limitColumn.getDirection() == OrderByColumnSpec.Direction.ASCENDING ? baseMetricSpec : new InvertedTopNMetricSpec(baseMetricSpec);
    } else if (plannerContext.getPlannerConfig().isUseApproximateTopN()) {
        // ORDER BY metric
        final NumericTopNMetricSpec baseMetricSpec = new NumericTopNMetricSpec(limitColumn.getDimension());
        topNMetricSpec = limitColumn.getDirection() == OrderByColumnSpec.Direction.ASCENDING ? new InvertedTopNMetricSpec(baseMetricSpec) : baseMetricSpec;
    } else {
        return null;
    }
    final Pair<DataSource, Filtration> dataSourceFiltrationPair = getFiltration(dataSource, filter, virtualColumnRegistry);
    final DataSource newDataSource = dataSourceFiltrationPair.lhs;
    final Filtration filtration = dataSourceFiltrationPair.rhs;
    final List<PostAggregator> postAggregators = new ArrayList<>(grouping.getPostAggregators());
    if (sorting.getProjection() != null) {
        postAggregators.addAll(sorting.getProjection().getPostAggregators());
    }
    return new TopNQuery(newDataSource, getVirtualColumns(true), dimensionSpec, topNMetricSpec, Ints.checkedCast(sorting.getOffsetLimit().getLimit()), filtration.getQuerySegmentSpec(), filtration.getDimFilter(), Granularities.ALL, grouping.getAggregatorFactories(), postAggregators, ImmutableSortedMap.copyOf(plannerContext.getQueryContext()));
}
Also used : DimensionSpec(org.apache.druid.query.dimension.DimensionSpec) Filtration(org.apache.druid.sql.calcite.filtration.Filtration) PostAggregator(org.apache.druid.query.aggregation.PostAggregator) IntArrayList(it.unimi.dsi.fastutil.ints.IntArrayList) ArrayList(java.util.ArrayList) InvertedTopNMetricSpec(org.apache.druid.query.topn.InvertedTopNMetricSpec) TopNMetricSpec(org.apache.druid.query.topn.TopNMetricSpec) NumericTopNMetricSpec(org.apache.druid.query.topn.NumericTopNMetricSpec) DimensionTopNMetricSpec(org.apache.druid.query.topn.DimensionTopNMetricSpec) DataSource(org.apache.druid.query.DataSource) QueryDataSource(org.apache.druid.query.QueryDataSource) JoinDataSource(org.apache.druid.query.JoinDataSource) OrderByColumnSpec(org.apache.druid.query.groupby.orderby.OrderByColumnSpec) DimensionTopNMetricSpec(org.apache.druid.query.topn.DimensionTopNMetricSpec) InvertedTopNMetricSpec(org.apache.druid.query.topn.InvertedTopNMetricSpec) NumericTopNMetricSpec(org.apache.druid.query.topn.NumericTopNMetricSpec) TopNQuery(org.apache.druid.query.topn.TopNQuery) Nullable(javax.annotation.Nullable)

Example 55 with OrderByColumnSpec

use of org.apache.druid.query.groupby.orderby.OrderByColumnSpec in project druid by druid-io.

the class DruidQuery method computeSorting.

@Nonnull
private static Sorting computeSorting(final PartialDruidQuery partialQuery, final PlannerContext plannerContext, final RowSignature rowSignature, @Nullable final VirtualColumnRegistry virtualColumnRegistry) {
    final Sort sort = Preconditions.checkNotNull(partialQuery.getSort(), "sort");
    final Project sortProject = partialQuery.getSortProject();
    // Extract limit and offset.
    final OffsetLimit offsetLimit = OffsetLimit.fromSort(sort);
    // Extract orderBy column specs.
    final List<OrderByColumnSpec> orderBys = new ArrayList<>(sort.getChildExps().size());
    for (int sortKey = 0; sortKey < sort.getChildExps().size(); sortKey++) {
        final RexNode sortExpression = sort.getChildExps().get(sortKey);
        final RelFieldCollation collation = sort.getCollation().getFieldCollations().get(sortKey);
        final OrderByColumnSpec.Direction direction;
        final StringComparator comparator;
        if (collation.getDirection() == RelFieldCollation.Direction.ASCENDING) {
            direction = OrderByColumnSpec.Direction.ASCENDING;
        } else if (collation.getDirection() == RelFieldCollation.Direction.DESCENDING) {
            direction = OrderByColumnSpec.Direction.DESCENDING;
        } else {
            throw new ISE("Don't know what to do with direction[%s]", collation.getDirection());
        }
        final SqlTypeName sortExpressionType = sortExpression.getType().getSqlTypeName();
        if (SqlTypeName.NUMERIC_TYPES.contains(sortExpressionType) || SqlTypeName.TIMESTAMP == sortExpressionType || SqlTypeName.DATE == sortExpressionType) {
            comparator = StringComparators.NUMERIC;
        } else {
            comparator = StringComparators.LEXICOGRAPHIC;
        }
        if (sortExpression.isA(SqlKind.INPUT_REF)) {
            final RexInputRef ref = (RexInputRef) sortExpression;
            final String fieldName = rowSignature.getColumnName(ref.getIndex());
            orderBys.add(new OrderByColumnSpec(fieldName, direction, comparator));
        } else {
            // We don't support sorting by anything other than refs which actually appear in the query result.
            throw new CannotBuildQueryException(sort, sortExpression);
        }
    }
    // Extract any post-sort Projection.
    final Projection projection;
    if (sortProject == null) {
        projection = null;
    } else if (partialQuery.getAggregate() == null) {
        if (virtualColumnRegistry == null) {
            throw new ISE("Must provide 'virtualColumnRegistry' for pre-aggregation Projection!");
        }
        projection = Projection.preAggregation(sortProject, plannerContext, rowSignature, virtualColumnRegistry);
    } else {
        projection = Projection.postAggregation(sortProject, plannerContext, rowSignature, "s");
    }
    return Sorting.create(orderBys, offsetLimit, projection);
}
Also used : OffsetLimit(org.apache.druid.sql.calcite.planner.OffsetLimit) SqlTypeName(org.apache.calcite.sql.type.SqlTypeName) IntArrayList(it.unimi.dsi.fastutil.ints.IntArrayList) ArrayList(java.util.ArrayList) StringComparator(org.apache.druid.query.ordering.StringComparator) OrderByColumnSpec(org.apache.druid.query.groupby.orderby.OrderByColumnSpec) Project(org.apache.calcite.rel.core.Project) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) Sort(org.apache.calcite.rel.core.Sort) RexInputRef(org.apache.calcite.rex.RexInputRef) ISE(org.apache.druid.java.util.common.ISE) RexNode(org.apache.calcite.rex.RexNode) Nonnull(javax.annotation.Nonnull)

Aggregations

OrderByColumnSpec (org.apache.druid.query.groupby.orderby.OrderByColumnSpec)111 DefaultDimensionSpec (org.apache.druid.query.dimension.DefaultDimensionSpec)105 Test (org.junit.Test)104 DefaultLimitSpec (org.apache.druid.query.groupby.orderby.DefaultLimitSpec)99 LongSumAggregatorFactory (org.apache.druid.query.aggregation.LongSumAggregatorFactory)79 InitializedNullHandlingTest (org.apache.druid.testing.InitializedNullHandlingTest)46 MultipleIntervalSegmentSpec (org.apache.druid.query.spec.MultipleIntervalSegmentSpec)15 FinalizeResultsQueryRunner (org.apache.druid.query.FinalizeResultsQueryRunner)11 QueryPlus (org.apache.druid.query.QueryPlus)10 QueryRunner (org.apache.druid.query.QueryRunner)10 ResponseContext (org.apache.druid.query.context.ResponseContext)10 CountAggregatorFactory (org.apache.druid.query.aggregation.CountAggregatorFactory)9 GreaterThanHavingSpec (org.apache.druid.query.groupby.having.GreaterThanHavingSpec)8 QuerySegmentSpec (org.apache.druid.query.spec.QuerySegmentSpec)8 ExpressionVirtualColumn (org.apache.druid.segment.virtual.ExpressionVirtualColumn)7 ListFilteredVirtualColumn (org.apache.druid.segment.virtual.ListFilteredVirtualColumn)7 ArrayList (java.util.ArrayList)6 Sequence (org.apache.druid.java.util.common.guava.Sequence)6 QueryDataSource (org.apache.druid.query.QueryDataSource)6 GroupByQuery (org.apache.druid.query.groupby.GroupByQuery)6