Search in sources :

Example 1 with StringComparator

use of org.apache.druid.query.ordering.StringComparator 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)

Example 2 with StringComparator

use of org.apache.druid.query.ordering.StringComparator in project druid by druid-io.

the class ConvertBoundsToSelectors method process.

@Override
public DimFilter process(DimFilter filter) {
    if (filter instanceof BoundDimFilter) {
        final BoundDimFilter bound = (BoundDimFilter) filter;
        final StringComparator comparator = RowSignatures.getNaturalStringComparator(rowSignature, SimpleExtraction.of(bound.getDimension(), bound.getExtractionFn()));
        if (bound.hasUpperBound() && bound.hasLowerBound() && bound.getUpper().equals(bound.getLower()) && !bound.isUpperStrict() && !bound.isLowerStrict() && bound.getOrdering().equals(comparator)) {
            return new SelectorDimFilter(bound.getDimension(), bound.getUpper(), bound.getExtractionFn());
        } else {
            return filter;
        }
    } else {
        return filter;
    }
}
Also used : BoundDimFilter(org.apache.druid.query.filter.BoundDimFilter) SelectorDimFilter(org.apache.druid.query.filter.SelectorDimFilter) StringComparator(org.apache.druid.query.ordering.StringComparator)

Example 3 with StringComparator

use of org.apache.druid.query.ordering.StringComparator in project druid by druid-io.

the class GroupByQuery method compareDimsForLimitPushDown.

private static int compareDimsForLimitPushDown(final IntList fields, final List<Boolean> needsReverseList, final List<ColumnType> dimensionTypes, final List<StringComparator> comparators, final ResultRow lhs, final ResultRow rhs) {
    for (int i = 0; i < fields.size(); i++) {
        final int fieldNumber = fields.getInt(i);
        final StringComparator comparator = comparators.get(i);
        final ColumnType dimensionType = dimensionTypes.get(i);
        final int dimCompare;
        final Object lhsObj = lhs.get(fieldNumber);
        final Object rhsObj = rhs.get(fieldNumber);
        if (dimensionType.isNumeric()) {
            if (comparator.equals(StringComparators.NUMERIC)) {
                dimCompare = DimensionHandlerUtils.compareObjectsAsType(lhsObj, rhsObj, dimensionType);
            } else {
                dimCompare = comparator.compare(String.valueOf(lhsObj), String.valueOf(rhsObj));
            }
        } else if (dimensionType.equals(ColumnType.STRING_ARRAY)) {
            final ComparableStringArray lhsArr = DimensionHandlerUtils.convertToComparableStringArray(lhsObj);
            final ComparableStringArray rhsArr = DimensionHandlerUtils.convertToComparableStringArray(rhsObj);
            dimCompare = Comparators.<Comparable>naturalNullsFirst().compare(lhsArr, rhsArr);
        } else if (dimensionType.equals(ColumnType.LONG_ARRAY) || dimensionType.equals(ColumnType.DOUBLE_ARRAY)) {
            final ComparableList lhsArr = DimensionHandlerUtils.convertToList(lhsObj);
            final ComparableList rhsArr = DimensionHandlerUtils.convertToList(rhsObj);
            dimCompare = Comparators.<Comparable>naturalNullsFirst().compare(lhsArr, rhsArr);
        } else {
            dimCompare = comparator.compare((String) lhsObj, (String) rhsObj);
        }
        if (dimCompare != 0) {
            return needsReverseList.get(i) ? -dimCompare : dimCompare;
        }
    }
    return 0;
}
Also used : ColumnType(org.apache.druid.segment.column.ColumnType) ComparableList(org.apache.druid.segment.data.ComparableList) ComparableStringArray(org.apache.druid.segment.data.ComparableStringArray) StringComparator(org.apache.druid.query.ordering.StringComparator)

Example 4 with StringComparator

use of org.apache.druid.query.ordering.StringComparator in project druid by druid-io.

the class GroupByQuery method getRowOrderingForPushDown.

/**
 * When limit push down is applied, the partial results would be sorted by the ordering specified by the
 * limit/order spec (unlike non-push down case where the results always use the default natural ascending order),
 * so when merging these partial result streams, the merge needs to use the same ordering to get correct results.
 */
private Ordering<ResultRow> getRowOrderingForPushDown(final boolean granular, final DefaultLimitSpec limitSpec) {
    final boolean sortByDimsFirst = getContextSortByDimsFirst();
    final IntList orderedFieldNumbers = new IntArrayList();
    final Set<Integer> dimsInOrderBy = new HashSet<>();
    final List<Boolean> needsReverseList = new ArrayList<>();
    final List<ColumnType> dimensionTypes = new ArrayList<>();
    final List<StringComparator> comparators = new ArrayList<>();
    for (OrderByColumnSpec orderSpec : limitSpec.getColumns()) {
        boolean needsReverse = orderSpec.getDirection() != OrderByColumnSpec.Direction.ASCENDING;
        int dimIndex = OrderByColumnSpec.getDimIndexForOrderBy(orderSpec, dimensions);
        if (dimIndex >= 0) {
            DimensionSpec dim = dimensions.get(dimIndex);
            orderedFieldNumbers.add(resultRowSignature.indexOf(dim.getOutputName()));
            dimsInOrderBy.add(dimIndex);
            needsReverseList.add(needsReverse);
            final ColumnType type = dimensions.get(dimIndex).getOutputType();
            dimensionTypes.add(type);
            comparators.add(orderSpec.getDimensionComparator());
        }
    }
    for (int i = 0; i < dimensions.size(); i++) {
        if (!dimsInOrderBy.contains(i)) {
            orderedFieldNumbers.add(resultRowSignature.indexOf(dimensions.get(i).getOutputName()));
            needsReverseList.add(false);
            final ColumnType type = dimensions.get(i).getOutputType();
            dimensionTypes.add(type);
            comparators.add(StringComparators.LEXICOGRAPHIC);
        }
    }
    final Comparator<ResultRow> timeComparator = getTimeComparator(granular);
    if (timeComparator == null) {
        return Ordering.from((lhs, rhs) -> compareDimsForLimitPushDown(orderedFieldNumbers, needsReverseList, dimensionTypes, comparators, lhs, rhs));
    } else if (sortByDimsFirst) {
        return Ordering.from((lhs, rhs) -> {
            final int cmp = compareDimsForLimitPushDown(orderedFieldNumbers, needsReverseList, dimensionTypes, comparators, lhs, rhs);
            if (cmp != 0) {
                return cmp;
            }
            return timeComparator.compare(lhs, rhs);
        });
    } else {
        return Ordering.from((lhs, rhs) -> {
            final int timeCompare = timeComparator.compare(lhs, rhs);
            if (timeCompare != 0) {
                return timeCompare;
            }
            return compareDimsForLimitPushDown(orderedFieldNumbers, needsReverseList, dimensionTypes, comparators, lhs, rhs);
        });
    }
}
Also used : JsonProperty(com.fasterxml.jackson.annotation.JsonProperty) Arrays(java.util.Arrays) Comparators(org.apache.druid.java.util.common.guava.Comparators) DimensionHandlerUtils(org.apache.druid.segment.DimensionHandlerUtils) DefaultLimitSpec(org.apache.druid.query.groupby.orderby.DefaultLimitSpec) DefaultDimensionSpec(org.apache.druid.query.dimension.DefaultDimensionSpec) OrderByColumnSpec(org.apache.druid.query.groupby.orderby.OrderByColumnSpec) PostAggregator(org.apache.druid.query.aggregation.PostAggregator) Map(java.util.Map) IAE(org.apache.druid.java.util.common.IAE) DateTimes(org.apache.druid.java.util.common.DateTimes) Sequence(org.apache.druid.java.util.common.guava.Sequence) Longs(com.google.common.primitives.Longs) Function(com.google.common.base.Function) ImmutableMap(com.google.common.collect.ImmutableMap) DataSource(org.apache.druid.query.DataSource) AggregatorFactory(org.apache.druid.query.aggregation.AggregatorFactory) Set(java.util.Set) ISE(org.apache.druid.java.util.common.ISE) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) QuerySegmentSpec(org.apache.druid.query.spec.QuerySegmentSpec) Objects(java.util.Objects) QueryDataSource(org.apache.druid.query.QueryDataSource) List(java.util.List) DimFilter(org.apache.druid.query.filter.DimFilter) DimensionSpec(org.apache.druid.query.dimension.DimensionSpec) IntArrayList(it.unimi.dsi.fastutil.ints.IntArrayList) HavingSpec(org.apache.druid.query.groupby.having.HavingSpec) NoopLimitSpec(org.apache.druid.query.groupby.orderby.NoopLimitSpec) Granularity(org.apache.druid.java.util.common.granularity.Granularity) ComparableList(org.apache.druid.segment.data.ComparableList) BaseQuery(org.apache.druid.query.BaseQuery) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Interval(org.joda.time.Interval) Lists(com.google.common.collect.Lists) ColumnHolder(org.apache.druid.segment.column.ColumnHolder) ImmutableList(com.google.common.collect.ImmutableList) Query(org.apache.druid.query.Query) JsonIgnore(com.fasterxml.jackson.annotation.JsonIgnore) StringComparators(org.apache.druid.query.ordering.StringComparators) ComparableStringArray(org.apache.druid.segment.data.ComparableStringArray) Sequences(org.apache.druid.java.util.common.guava.Sequences) Nullable(javax.annotation.Nullable) Functions(com.google.common.base.Functions) VirtualColumns(org.apache.druid.segment.VirtualColumns) StringComparator(org.apache.druid.query.ordering.StringComparator) VirtualColumn(org.apache.druid.segment.VirtualColumn) DateTime(org.joda.time.DateTime) LimitSpec(org.apache.druid.query.groupby.orderby.LimitSpec) TableDataSource(org.apache.druid.query.TableDataSource) Granularities(org.apache.druid.java.util.common.granularity.Granularities) Queries(org.apache.druid.query.Queries) IntList(it.unimi.dsi.fastutil.ints.IntList) Ordering(com.google.common.collect.Ordering) LegacySegmentSpec(org.apache.druid.query.spec.LegacySegmentSpec) RowSignature(org.apache.druid.segment.column.RowSignature) JsonCreator(com.fasterxml.jackson.annotation.JsonCreator) JsonInclude(com.fasterxml.jackson.annotation.JsonInclude) ColumnType(org.apache.druid.segment.column.ColumnType) Preconditions(com.google.common.base.Preconditions) Comparator(java.util.Comparator) Collections(java.util.Collections) DefaultDimensionSpec(org.apache.druid.query.dimension.DefaultDimensionSpec) DimensionSpec(org.apache.druid.query.dimension.DimensionSpec) ColumnType(org.apache.druid.segment.column.ColumnType) IntArrayList(it.unimi.dsi.fastutil.ints.IntArrayList) ArrayList(java.util.ArrayList) StringComparator(org.apache.druid.query.ordering.StringComparator) IntList(it.unimi.dsi.fastutil.ints.IntList) OrderByColumnSpec(org.apache.druid.query.groupby.orderby.OrderByColumnSpec) IntArrayList(it.unimi.dsi.fastutil.ints.IntArrayList) HashSet(java.util.HashSet)

Example 5 with StringComparator

use of org.apache.druid.query.ordering.StringComparator in project druid by druid-io.

the class StringGroupByColumnSelectorStrategy method bufferComparator.

@Override
public Grouper.BufferComparator bufferComparator(int keyBufferPosition, @Nullable StringComparator stringComparator) {
    final boolean canCompareInts = capabilities != null && capabilities.hasBitmapIndexes() && capabilities.areDictionaryValuesSorted().and(capabilities.areDictionaryValuesUnique()).isTrue();
    final StringComparator comparator = stringComparator == null ? StringComparators.LEXICOGRAPHIC : stringComparator;
    if (canCompareInts && StringComparators.LEXICOGRAPHIC.equals(comparator)) {
        return (lhsBuffer, rhsBuffer, lhsPosition, rhsPosition) -> Integer.compare(lhsBuffer.getInt(lhsPosition + keyBufferPosition), rhsBuffer.getInt(rhsPosition + keyBufferPosition));
    } else {
        Preconditions.checkState(dictionaryLookup != null, "null dictionary lookup");
        return (lhsBuffer, rhsBuffer, lhsPosition, rhsPosition) -> {
            String lhsStr = dictionaryLookup.apply(lhsBuffer.getInt(lhsPosition + keyBufferPosition));
            String rhsStr = dictionaryLookup.apply(rhsBuffer.getInt(rhsPosition + keyBufferPosition));
            return comparator.compare(lhsStr, rhsStr);
        };
    }
}
Also used : StringComparator(org.apache.druid.query.ordering.StringComparator) ResultRow(org.apache.druid.query.groupby.ResultRow) ColumnValueSelector(org.apache.druid.segment.ColumnValueSelector) Grouper(org.apache.druid.query.groupby.epinephelinae.Grouper) IndexedInts(org.apache.druid.segment.data.IndexedInts) ByteBuffer(java.nio.ByteBuffer) NullHandling(org.apache.druid.common.config.NullHandling) StringComparators(org.apache.druid.query.ordering.StringComparators) ColumnCapabilities(org.apache.druid.segment.column.ColumnCapabilities) Preconditions(com.google.common.base.Preconditions) DimensionSelector(org.apache.druid.segment.DimensionSelector) Nullable(javax.annotation.Nullable) IntFunction(java.util.function.IntFunction) StringComparator(org.apache.druid.query.ordering.StringComparator)

Aggregations

StringComparator (org.apache.druid.query.ordering.StringComparator)12 ArrayList (java.util.ArrayList)5 List (java.util.List)5 Nullable (javax.annotation.Nullable)5 ISE (org.apache.druid.java.util.common.ISE)4 OrderByColumnSpec (org.apache.druid.query.groupby.orderby.OrderByColumnSpec)4 ColumnType (org.apache.druid.segment.column.ColumnType)4 Preconditions (com.google.common.base.Preconditions)3 ImmutableList (com.google.common.collect.ImmutableList)3 ByteBuffer (java.nio.ByteBuffer)3 HashSet (java.util.HashSet)3 StringComparators (org.apache.druid.query.ordering.StringComparators)3 ComparableList (org.apache.druid.segment.data.ComparableList)3 ComparableStringArray (org.apache.druid.segment.data.ComparableStringArray)3 JsonCreator (com.fasterxml.jackson.annotation.JsonCreator)2 JsonInclude (com.fasterxml.jackson.annotation.JsonInclude)2 JsonProperty (com.fasterxml.jackson.annotation.JsonProperty)2 Function (com.google.common.base.Function)2 Functions (com.google.common.base.Functions)2 Ordering (com.google.common.collect.Ordering)2