Search in sources :

Example 1 with RuntimeShapeInspector

use of org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector in project druid by druid-io.

the class OrFilter method makeMatcher.

private static ValueMatcher makeMatcher(final ValueMatcher[] baseMatchers) {
    Preconditions.checkState(baseMatchers.length > 0);
    if (baseMatchers.length == 1) {
        return baseMatchers[0];
    }
    return new ValueMatcher() {

        @Override
        public boolean matches() {
            for (ValueMatcher matcher : baseMatchers) {
                if (matcher.matches()) {
                    return true;
                }
            }
            return false;
        }

        @Override
        public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
            inspector.visit("firstBaseMatcher", baseMatchers[0]);
            inspector.visit("secondBaseMatcher", baseMatchers[1]);
        // Don't inspect the 3rd and all consequent baseMatchers, cut runtime shape combinations at this point.
        // Anyway if the filter is so complex, Hotspot won't inline all calls because of the inline limit.
        }
    };
}
Also used : ValueMatcher(org.apache.druid.query.filter.ValueMatcher) BaseVectorValueMatcher(org.apache.druid.query.filter.vector.BaseVectorValueMatcher) VectorValueMatcher(org.apache.druid.query.filter.vector.VectorValueMatcher) RuntimeShapeInspector(org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector)

Example 2 with RuntimeShapeInspector

use of org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector in project druid by druid-io.

the class RowBasedColumnSelectorFactory method makeDimensionSelectorUndecorated.

private DimensionSelector makeDimensionSelectorUndecorated(DimensionSpec dimensionSpec) {
    final String dimension = dimensionSpec.getDimension();
    final ExtractionFn extractionFn = dimensionSpec.getExtractionFn();
    if (ColumnHolder.TIME_COLUMN_NAME.equals(dimensionSpec.getDimension())) {
        if (extractionFn == null) {
            throw new UnsupportedOperationException("time dimension must provide an extraction function");
        }
        final ToLongFunction<T> timestampFunction = adapter.timestampFunction();
        return new BaseSingleValueDimensionSelector() {

            private long currentId = NO_ID;

            private String currentValue;

            @Override
            protected String getValue() {
                updateCurrentValue();
                return currentValue;
            }

            @Override
            public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
                inspector.visit("row", rowSupplier);
                inspector.visit("extractionFn", extractionFn);
            }

            private void updateCurrentValue() {
                if (rowIdSupplier == null || rowIdSupplier.getAsLong() != currentId) {
                    currentValue = extractionFn.apply(timestampFunction.applyAsLong(rowSupplier.get()));
                    if (rowIdSupplier != null) {
                        currentId = rowIdSupplier.getAsLong();
                    }
                }
            }
        };
    } else {
        final Function<T, Object> dimFunction = adapter.columnFunction(dimension);
        return new DimensionSelector() {

            private long currentId = NO_ID;

            private List<String> dimensionValues;

            private final RangeIndexedInts indexedInts = new RangeIndexedInts();

            @Override
            public IndexedInts getRow() {
                updateCurrentValues();
                indexedInts.setSize(dimensionValues.size());
                return indexedInts;
            }

            @Override
            public ValueMatcher makeValueMatcher(@Nullable final String value) {
                return new ValueMatcher() {

                    @Override
                    public boolean matches() {
                        updateCurrentValues();
                        if (dimensionValues.isEmpty()) {
                            return value == null;
                        }
                        for (String dimensionValue : dimensionValues) {
                            if (Objects.equals(NullHandling.emptyToNullIfNeeded(dimensionValue), value)) {
                                return true;
                            }
                        }
                        return false;
                    }

                    @Override
                    public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
                        inspector.visit("row", rowSupplier);
                        inspector.visit("extractionFn", extractionFn);
                    }
                };
            }

            @Override
            public ValueMatcher makeValueMatcher(final Predicate<String> predicate) {
                final boolean matchNull = predicate.apply(null);
                return new ValueMatcher() {

                    @Override
                    public boolean matches() {
                        updateCurrentValues();
                        if (dimensionValues.isEmpty()) {
                            return matchNull;
                        }
                        for (String dimensionValue : dimensionValues) {
                            if (predicate.apply(NullHandling.emptyToNullIfNeeded(dimensionValue))) {
                                return true;
                            }
                        }
                        return false;
                    }

                    @Override
                    public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
                        inspector.visit("row", rowSupplier);
                        inspector.visit("predicate", predicate);
                        inspector.visit("extractionFn", extractionFn);
                    }
                };
            }

            @Override
            public int getValueCardinality() {
                return DimensionDictionarySelector.CARDINALITY_UNKNOWN;
            }

            @Override
            public String lookupName(int id) {
                updateCurrentValues();
                return NullHandling.emptyToNullIfNeeded(dimensionValues.get(id));
            }

            @Override
            public boolean nameLookupPossibleInAdvance() {
                return false;
            }

            @Nullable
            @Override
            public IdLookup idLookup() {
                return null;
            }

            @Nullable
            @Override
            public Object getObject() {
                updateCurrentValues();
                if (dimensionValues.size() == 1) {
                    return dimensionValues.get(0);
                }
                return dimensionValues;
            }

            @Override
            public Class classOfObject() {
                return Object.class;
            }

            @Override
            public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
                inspector.visit("row", rowSupplier);
                inspector.visit("extractionFn", extractionFn);
            }

            private void updateCurrentValues() {
                if (rowIdSupplier == null || rowIdSupplier.getAsLong() != currentId) {
                    try {
                        final Object rawValue = dimFunction.apply(rowSupplier.get());
                        if (rawValue == null || rawValue instanceof String) {
                            final String s = NullHandling.emptyToNullIfNeeded((String) rawValue);
                            if (extractionFn == null) {
                                dimensionValues = Collections.singletonList(s);
                            } else {
                                dimensionValues = Collections.singletonList(extractionFn.apply(s));
                            }
                        } else if (rawValue instanceof List) {
                            // Consistent behavior with Rows.objectToStrings, but applies extractionFn too.
                            // noinspection rawtypes
                            final List<String> values = new ArrayList<>(((List) rawValue).size());
                            // noinspection rawtypes
                            for (final Object item : ((List) rawValue)) {
                                // commonly used when retrieving strings from input-row-like objects.
                                if (extractionFn == null) {
                                    values.add(String.valueOf(item));
                                } else {
                                    values.add(extractionFn.apply(String.valueOf(item)));
                                }
                            }
                            dimensionValues = values;
                        } else {
                            final List<String> nonExtractedValues = Rows.objectToStrings(rawValue);
                            dimensionValues = new ArrayList<>(nonExtractedValues.size());
                            for (final String value : nonExtractedValues) {
                                final String s = NullHandling.emptyToNullIfNeeded(value);
                                if (extractionFn == null) {
                                    dimensionValues.add(s);
                                } else {
                                    dimensionValues.add(extractionFn.apply(s));
                                }
                            }
                        }
                    } catch (Throwable e) {
                        currentId = NO_ID;
                        throw e;
                    }
                    if (rowIdSupplier != null) {
                        currentId = rowIdSupplier.getAsLong();
                    }
                }
            }
        };
    }
}
Also used : ValueMatcher(org.apache.druid.query.filter.ValueMatcher) ArrayList(java.util.ArrayList) RuntimeShapeInspector(org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector) RangeIndexedInts(org.apache.druid.segment.data.RangeIndexedInts) Predicate(com.google.common.base.Predicate) ExtractionFn(org.apache.druid.query.extraction.ExtractionFn) ArrayList(java.util.ArrayList) List(java.util.List) Nullable(javax.annotation.Nullable)

Example 3 with RuntimeShapeInspector

use of org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector 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();
    }
}
Also used : HistoricalDimensionSelector(org.apache.druid.segment.historical.HistoricalDimensionSelector) SingleValueHistoricalDimensionSelector(org.apache.druid.segment.historical.SingleValueHistoricalDimensionSelector) ValueMatcher(org.apache.druid.query.filter.ValueMatcher) BooleanValueMatcher(org.apache.druid.segment.filter.BooleanValueMatcher) SingleIndexedInt(org.apache.druid.segment.data.SingleIndexedInt) BitSet(java.util.BitSet) RuntimeShapeInspector(org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector) SingleValueHistoricalDimensionSelector(org.apache.druid.segment.historical.SingleValueHistoricalDimensionSelector) Predicate(com.google.common.base.Predicate) IdLookup(org.apache.druid.segment.IdLookup) AbstractDimensionSelector(org.apache.druid.segment.AbstractDimensionSelector) Nullable(javax.annotation.Nullable)

Example 4 with RuntimeShapeInspector

use of org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector in project druid by druid-io.

the class QueryableIndexIndexableAdapter method getDimValueLookup.

@Nullable
@Override
public <T extends Comparable<? super T>> CloseableIndexed<T> getDimValueLookup(String dimension) {
    final ColumnHolder columnHolder = input.getColumnHolder(dimension);
    if (columnHolder == null) {
        return null;
    }
    final BaseColumn col = columnHolder.getColumn();
    if (!(col instanceof DictionaryEncodedColumn)) {
        return null;
    }
    @SuppressWarnings("unchecked") DictionaryEncodedColumn<T> dict = (DictionaryEncodedColumn<T>) col;
    return new CloseableIndexed<T>() {

        @Override
        public int size() {
            return dict.getCardinality();
        }

        @Override
        public T get(int index) {
            return dict.lookupName(index);
        }

        @Override
        public int indexOf(T value) {
            return dict.lookupId(value);
        }

        @Override
        public Iterator<T> iterator() {
            return IndexedIterable.create(this).iterator();
        }

        @Override
        public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
            inspector.visit("dict", dict);
        }

        @Override
        public void close() throws IOException {
            dict.close();
        }
    };
}
Also used : ColumnHolder(org.apache.druid.segment.column.ColumnHolder) RuntimeShapeInspector(org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector) BaseColumn(org.apache.druid.segment.column.BaseColumn) DictionaryEncodedColumn(org.apache.druid.segment.column.DictionaryEncodedColumn) CloseableIndexed(org.apache.druid.segment.data.CloseableIndexed) Nullable(javax.annotation.Nullable)

Example 5 with RuntimeShapeInspector

use of org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector in project druid by druid-io.

the class GenericIndexed method singleThreadedVersionOne.

private BufferIndexed singleThreadedVersionOne() {
    final ByteBuffer copyBuffer = firstValueBuffer.asReadOnlyBuffer();
    return new BufferIndexed() {

        @Override
        public T get(final int index) {
            checkIndex(index);
            final int startOffset;
            final int endOffset;
            if (index == 0) {
                startOffset = Integer.BYTES;
                endOffset = headerBuffer.getInt(0);
            } else {
                int headerPosition = (index - 1) * Integer.BYTES;
                startOffset = headerBuffer.getInt(headerPosition) + Integer.BYTES;
                endOffset = headerBuffer.getInt(headerPosition + Integer.BYTES);
            }
            return bufferedIndexedGet(copyBuffer, startOffset, endOffset);
        }

        @Override
        public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
            inspector.visit("headerBuffer", headerBuffer);
            inspector.visit("copyBuffer", copyBuffer);
            inspector.visit("strategy", strategy);
        }
    };
}
Also used : RuntimeShapeInspector(org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector) ByteBuffer(java.nio.ByteBuffer)

Aggregations

RuntimeShapeInspector (org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector)26 ValueMatcher (org.apache.druid.query.filter.ValueMatcher)19 IndexedInts (org.apache.druid.segment.data.IndexedInts)11 BooleanValueMatcher (org.apache.druid.segment.filter.BooleanValueMatcher)8 Nullable (javax.annotation.Nullable)7 Predicate (com.google.common.base.Predicate)5 ArrayBasedIndexedInts (org.apache.druid.segment.data.ArrayBasedIndexedInts)5 BitSet (java.util.BitSet)4 IdLookup (org.apache.druid.segment.IdLookup)4 DimensionSpec (org.apache.druid.query.dimension.DimensionSpec)3 ColumnSelectorFactory (org.apache.druid.segment.ColumnSelectorFactory)3 ColumnHolder (org.apache.druid.segment.column.ColumnHolder)3 Test (org.junit.Test)3 InputRow (org.apache.druid.data.input.InputRow)2 MapBasedInputRow (org.apache.druid.data.input.MapBasedInputRow)2 ISE (org.apache.druid.java.util.common.ISE)2 ExtractionFn (org.apache.druid.query.extraction.ExtractionFn)2 AbstractDimensionSelector (org.apache.druid.segment.AbstractDimensionSelector)2 ColumnValueSelector (org.apache.druid.segment.ColumnValueSelector)2 RowBasedColumnSelectorFactory (org.apache.druid.segment.RowBasedColumnSelectorFactory)2