use of org.apache.druid.segment.historical.SingleValueHistoricalDimensionSelector in project druid by druid-io.
the class StringDictionaryEncodedColumn method makeDimensionSelector.
@Override
public HistoricalDimensionSelector makeDimensionSelector(final ReadableOffset offset, @Nullable final ExtractionFn extractionFn) {
abstract class QueryableDimensionSelector extends AbstractDimensionSelector implements HistoricalDimensionSelector, IdLookup {
@Override
public int getValueCardinality() {
/*
This is technically wrong if
extractionFn != null && (extractionFn.getExtractionType() != ExtractionFn.ExtractionType.ONE_TO_ONE ||
!extractionFn.preservesOrdering())
However current behavior allows some GroupBy-V1 queries to work that wouldn't work otherwise and doesn't
cause any problems due to special handling of extractionFn everywhere.
See https://github.com/apache/druid/pull/8433
*/
return getCardinality();
}
@Override
public String lookupName(int id) {
final String value = StringDictionaryEncodedColumn.this.lookupName(id);
return extractionFn == null ? value : extractionFn.apply(value);
}
@Nullable
@Override
public ByteBuffer lookupNameUtf8(int id) {
return StringDictionaryEncodedColumn.this.lookupNameUtf8(id);
}
@Override
public boolean supportsLookupNameUtf8() {
return true;
}
@Override
public boolean nameLookupPossibleInAdvance() {
return true;
}
@Nullable
@Override
public IdLookup idLookup() {
return extractionFn == null ? this : null;
}
@Override
public int lookupId(String name) {
if (extractionFn != null) {
throw new UnsupportedOperationException("cannot perform lookup when applying an extraction function");
}
return StringDictionaryEncodedColumn.this.lookupId(name);
}
}
if (hasMultipleValues()) {
class MultiValueDimensionSelector extends QueryableDimensionSelector {
@Override
public IndexedInts getRow() {
return multiValueColumn.get(offset.getOffset());
}
@Override
public IndexedInts getRow(int offset) {
return multiValueColumn.get(offset);
}
@Override
public ValueMatcher makeValueMatcher(@Nullable String value) {
return DimensionSelectorUtils.makeValueMatcherGeneric(this, value);
}
@Override
public ValueMatcher makeValueMatcher(Predicate<String> predicate) {
return DimensionSelectorUtils.makeValueMatcherGeneric(this, predicate);
}
@Nullable
@Override
public Object getObject() {
return defaultGetObject();
}
@Override
public Class classOfObject() {
return Object.class;
}
@Override
public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
inspector.visit("multiValueColumn", multiValueColumn);
inspector.visit("offset", offset);
inspector.visit("extractionFn", extractionFn);
}
}
return new MultiValueDimensionSelector();
} else {
class SingleValueQueryableDimensionSelector extends QueryableDimensionSelector implements SingleValueHistoricalDimensionSelector {
private final SingleIndexedInt row = new SingleIndexedInt();
@Override
public IndexedInts getRow() {
row.setValue(getRowValue());
return row;
}
public int getRowValue() {
return column.get(offset.getOffset());
}
@Override
public IndexedInts getRow(int offset) {
row.setValue(getRowValue(offset));
return row;
}
@Override
public int getRowValue(int offset) {
return column.get(offset);
}
@Override
public ValueMatcher makeValueMatcher(@Nullable final String value) {
if (extractionFn == null) {
final int valueId = lookupId(value);
if (valueId >= 0) {
return new ValueMatcher() {
@Override
public boolean matches() {
return getRowValue() == valueId;
}
@Override
public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
inspector.visit("column", StringDictionaryEncodedColumn.this);
}
};
} else {
return BooleanValueMatcher.of(false);
}
} else {
// Employ caching BitSet optimization
return makeValueMatcher(Predicates.equalTo(value));
}
}
@Override
public ValueMatcher makeValueMatcher(final Predicate<String> predicate) {
final BitSet checkedIds = new BitSet(getCardinality());
final BitSet matchingIds = new BitSet(getCardinality());
// Lazy matcher; only check an id if matches() is called.
return new ValueMatcher() {
@Override
public boolean matches() {
final int id = getRowValue();
if (checkedIds.get(id)) {
return matchingIds.get(id);
} else {
final boolean matches = predicate.apply(lookupName(id));
checkedIds.set(id);
if (matches) {
matchingIds.set(id);
}
return matches;
}
}
@Override
public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
inspector.visit("column", StringDictionaryEncodedColumn.this);
}
};
}
@Override
public Object getObject() {
return lookupName(getRowValue());
}
@Override
public Class classOfObject() {
return String.class;
}
@Override
public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
inspector.visit("column", column);
inspector.visit("offset", offset);
inspector.visit("extractionFn", extractionFn);
}
}
return new SingleValueQueryableDimensionSelector();
}
}
use of org.apache.druid.segment.historical.SingleValueHistoricalDimensionSelector in project druid by druid-io.
the class PooledTopNAlgorithm method computeSpecializedScanAndAggregateImplementations.
private static void computeSpecializedScanAndAggregateImplementations() {
SPECIALIZED_SCAN_AND_AGGREGATE_IMPLEMENTATIONS.clear();
// The order of the following `if` blocks matters, "more specialized" implementations go first
if (SPECIALIZE_HISTORICAL_SINGLE_VALUE_DIM_SELECTOR_ONE_SIMPLE_DOUBLE_AGG_POOLED_TOPN) {
SPECIALIZED_SCAN_AND_AGGREGATE_IMPLEMENTATIONS.add((params, positions, theAggregators) -> {
if (theAggregators.length == 1) {
BufferAggregator aggregator = theAggregators[0];
final Cursor cursor = params.getCursor();
if (cursor instanceof HistoricalCursor && // doesn't clone offset anymore.
!(((HistoricalCursor) cursor).getOffset() instanceof FilteredOffset) && aggregator instanceof SimpleDoubleBufferAggregator && params.getDimSelector() instanceof SingleValueHistoricalDimensionSelector && ((SimpleDoubleBufferAggregator) aggregator).getSelector() instanceof HistoricalColumnSelector) {
return scanAndAggregateHistorical1SimpleDoubleAgg(params, positions, (SimpleDoubleBufferAggregator) aggregator, (HistoricalCursor) cursor, DEFAULT_HISTORICAL_SINGLE_VALUE_DIM_SELECTOR_ONE_SIMPLE_DOUBLE_AGG_SCANNER);
}
}
return -1;
});
}
if (SPECIALIZE_HISTORICAL_ONE_SIMPLE_DOUBLE_AGG_POOLED_TOPN) {
SPECIALIZED_SCAN_AND_AGGREGATE_IMPLEMENTATIONS.add((params, positions, theAggregators) -> {
if (theAggregators.length == 1) {
BufferAggregator aggregator = theAggregators[0];
final Cursor cursor = params.getCursor();
if (cursor instanceof HistoricalCursor && // doesn't clone offset anymore.
!(((HistoricalCursor) cursor).getOffset() instanceof FilteredOffset) && aggregator instanceof SimpleDoubleBufferAggregator && params.getDimSelector() instanceof HistoricalDimensionSelector && ((SimpleDoubleBufferAggregator) aggregator).getSelector() instanceof HistoricalColumnSelector) {
return scanAndAggregateHistorical1SimpleDoubleAgg(params, positions, (SimpleDoubleBufferAggregator) aggregator, (HistoricalCursor) cursor, DEFAULT_HISTORICAL_ONE_SIMPLE_DOUBLE_AGG_SCANNER);
}
}
return -1;
});
}
if (SPECIALIZE_GENERIC_ONE_AGG_POOLED_TOPN) {
SPECIALIZED_SCAN_AND_AGGREGATE_IMPLEMENTATIONS.add((params, positions, theAggregators) -> {
if (theAggregators.length == 1) {
return scanAndAggregateGeneric1Agg(params, positions, theAggregators[0], params.getCursor());
}
return -1;
});
}
if (SPECIALIZE_GENERIC_TWO_AGG_POOLED_TOPN) {
SPECIALIZED_SCAN_AND_AGGREGATE_IMPLEMENTATIONS.add((params, positions, theAggregators) -> {
if (theAggregators.length == 2) {
return scanAndAggregateGeneric2Agg(params, positions, theAggregators, params.getCursor());
}
return -1;
});
}
}
Aggregations