diff --git a/processing/src/main/java/io/druid/query/topn/types/StringTopNColumnSelectorStrategy.java b/processing/src/main/java/io/druid/query/topn/types/StringTopNColumnSelectorStrategy.java index ed89bbda1b0..76936ddc392 100644 --- a/processing/src/main/java/io/druid/query/topn/types/StringTopNColumnSelectorStrategy.java +++ b/processing/src/main/java/io/druid/query/topn/types/StringTopNColumnSelectorStrategy.java @@ -36,7 +36,7 @@ import java.util.Map; import java.util.function.Function; public class StringTopNColumnSelectorStrategy - implements TopNColumnSelectorStrategy> + implements TopNColumnSelectorStrategy, Aggregator[]>> { private final Function> dimensionValueConverter; @@ -73,7 +73,7 @@ public class StringTopNColumnSelectorStrategy } @Override - public Map makeDimExtractionAggregateStore() + public Map, Aggregator[]> makeDimExtractionAggregateStore() { return new HashMap<>(); } @@ -84,7 +84,7 @@ public class StringTopNColumnSelectorStrategy DimensionSelector selector, Cursor cursor, Aggregator[][] rowSelector, - Map aggregatesStore + Map, Aggregator[]> aggregatesStore ) { if (selector.getValueCardinality() != DimensionSelector.CARDINALITY_UNKNOWN) { @@ -96,11 +96,11 @@ public class StringTopNColumnSelectorStrategy @Override public void updateDimExtractionResults( - final Map aggregatesStore, + final Map, Aggregator[]> aggregatesStore, final TopNResultBuilder resultBuilder ) { - for (Map.Entry entry : aggregatesStore.entrySet()) { + for (Map.Entry, Aggregator[]> entry : aggregatesStore.entrySet()) { Aggregator[] aggs = entry.getValue(); if (aggs != null) { Object[] vals = new Object[aggs.length]; @@ -108,7 +108,7 @@ public class StringTopNColumnSelectorStrategy vals[i] = aggs[i].get(); } - final Comparable key = dimensionValueConverter.apply(entry.getKey()); + final Comparable key = dimensionValueConverter.apply(entry.getKey()); resultBuilder.addEntry(key, key, vals); } } @@ -119,7 +119,7 @@ public class StringTopNColumnSelectorStrategy Cursor cursor, DimensionSelector selector, Aggregator[][] rowSelector, - Map aggregatesStore + Map, Aggregator[]> aggregatesStore ) { long processedRows = 0; @@ -152,7 +152,7 @@ public class StringTopNColumnSelectorStrategy TopNQuery query, Cursor cursor, DimensionSelector selector, - Map aggregatesStore + Map, Aggregator[]> aggregatesStore ) { long processedRows = 0; diff --git a/processing/src/main/java/io/druid/query/topn/types/TopNColumnSelectorStrategyFactory.java b/processing/src/main/java/io/druid/query/topn/types/TopNColumnSelectorStrategyFactory.java index 08e76ff919e..5f29874f1c2 100644 --- a/processing/src/main/java/io/druid/query/topn/types/TopNColumnSelectorStrategyFactory.java +++ b/processing/src/main/java/io/druid/query/topn/types/TopNColumnSelectorStrategyFactory.java @@ -49,9 +49,13 @@ public class TopNColumnSelectorStrategyFactory implements ColumnSelectorStrategy case LONG: case FLOAT: case DOUBLE: + // When the selector is numeric, we want to use NumericTopNColumnSelectorStrategy. It aggregates using + // a numeric type and then converts to the desired output type after aggregating. We must be careful not to + // convert to an output type that cannot represent all possible values of the input type. + if (ValueType.isNumeric(dimensionType)) { // Return strategy that aggregates using the _output_ type, because this allows us to collapse values - // properly (numeric types cannot represent all values of other numeric types). + // properly (numeric types cannot always represent all values of other numeric types). return NumericTopNColumnSelectorStrategy.ofType(dimensionType, dimensionType); } else { // Return strategy that aggregates using the _input_ type. Here we are assuming that the output type can diff --git a/processing/src/main/java/io/druid/segment/DimensionHandlerUtils.java b/processing/src/main/java/io/druid/segment/DimensionHandlerUtils.java index c78715b442b..b89296e805a 100644 --- a/processing/src/main/java/io/druid/segment/DimensionHandlerUtils.java +++ b/processing/src/main/java/io/druid/segment/DimensionHandlerUtils.java @@ -343,10 +343,7 @@ public final class DimensionHandlerUtils } @Nullable - public static Comparable convertObjectToType( - @Nullable final Object obj, - final ValueType type - ) + public static Comparable convertObjectToType(@Nullable final Object obj, final ValueType type) { return convertObjectToType(obj, Preconditions.checkNotNull(type, "type"), false); }