Search in sources :

Example 21 with ValueMatcher

use of org.apache.druid.query.filter.ValueMatcher in project druid by druid-io.

the class ExpressionVirtualColumnTest method testDimensionSelector.

@Test
public void testDimensionSelector() {
    final DimensionSelector selector = X_PLUS_Y.makeDimensionSelector(new DefaultDimensionSpec("expr", "expr"), COLUMN_SELECTOR_FACTORY);
    final ValueMatcher nullMatcher = selector.makeValueMatcher((String) null);
    final ValueMatcher fiveMatcher = selector.makeValueMatcher("5");
    final ValueMatcher nonNullMatcher = selector.makeValueMatcher(Predicates.notNull());
    CURRENT_ROW.set(ROW0);
    Assert.assertEquals(true, nullMatcher.matches());
    Assert.assertEquals(false, fiveMatcher.matches());
    Assert.assertEquals(false, nonNullMatcher.matches());
    Assert.assertEquals(null, selector.lookupName(selector.getRow().get(0)));
    CURRENT_ROW.set(ROW1);
    if (NullHandling.replaceWithDefault()) {
        Assert.assertEquals(false, nullMatcher.matches());
        Assert.assertEquals(false, fiveMatcher.matches());
        Assert.assertEquals(true, nonNullMatcher.matches());
        Assert.assertEquals("4", selector.lookupName(selector.getRow().get(0)));
    } else {
        // y is null in row1
        Assert.assertEquals(true, nullMatcher.matches());
        Assert.assertEquals(false, fiveMatcher.matches());
        Assert.assertEquals(false, nonNullMatcher.matches());
        Assert.assertEquals(null, selector.lookupName(selector.getRow().get(0)));
    }
    CURRENT_ROW.set(ROW2);
    Assert.assertEquals(false, nullMatcher.matches());
    Assert.assertEquals(false, fiveMatcher.matches());
    Assert.assertEquals(true, nonNullMatcher.matches());
    Assert.assertEquals("5.1", selector.lookupName(selector.getRow().get(0)));
    CURRENT_ROW.set(ROW3);
    Assert.assertEquals(false, nullMatcher.matches());
    Assert.assertEquals(true, fiveMatcher.matches());
    Assert.assertEquals(true, nonNullMatcher.matches());
    Assert.assertEquals("5", selector.lookupName(selector.getRow().get(0)));
}
Also used : ConstantMultiValueDimensionSelector(org.apache.druid.segment.ConstantMultiValueDimensionSelector) DimensionSelector(org.apache.druid.segment.DimensionSelector) ConstantDimensionSelector(org.apache.druid.segment.ConstantDimensionSelector) ValueMatcher(org.apache.druid.query.filter.ValueMatcher) DefaultDimensionSpec(org.apache.druid.query.dimension.DefaultDimensionSpec) InitializedNullHandlingTest(org.apache.druid.testing.InitializedNullHandlingTest) Test(org.junit.Test)

Example 22 with ValueMatcher

use of org.apache.druid.query.filter.ValueMatcher in project druid by druid-io.

the class DimensionSelectorUtils method makeDictionaryEncodedValueMatcherGeneric.

private static ValueMatcher makeDictionaryEncodedValueMatcherGeneric(final DimensionSelector selector, final int valueId, final boolean matchNull) {
    if (valueId >= 0) {
        return new ValueMatcher() {

            @Override
            public boolean matches() {
                final IndexedInts row = selector.getRow();
                final int size = row.size();
                if (size == 0) {
                    // null should match empty rows in multi-value columns
                    return matchNull;
                } else {
                    for (int i = 0; i < size; ++i) {
                        if (row.get(i) == valueId) {
                            return true;
                        }
                    }
                    return false;
                }
            }

            @Override
            public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
                inspector.visit("selector", selector);
            }
        };
    } else {
        if (matchNull) {
            return new ValueMatcher() {

                @Override
                public boolean matches() {
                    final IndexedInts row = selector.getRow();
                    final int size = row.size();
                    return size == 0;
                }

                @Override
                public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
                    inspector.visit("selector", selector);
                }
            };
        } else {
            return BooleanValueMatcher.of(false);
        }
    }
}
Also used : ValueMatcher(org.apache.druid.query.filter.ValueMatcher) BooleanValueMatcher(org.apache.druid.segment.filter.BooleanValueMatcher) IndexedInts(org.apache.druid.segment.data.IndexedInts) RuntimeShapeInspector(org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector)

Example 23 with ValueMatcher

use of org.apache.druid.query.filter.ValueMatcher in project druid by druid-io.

the class StringDimensionIndexer method makeDimensionSelector.

@Override
public DimensionSelector makeDimensionSelector(final DimensionSpec spec, final IncrementalIndexRowHolder currEntry, final IncrementalIndex.DimensionDesc desc) {
    final ExtractionFn extractionFn = spec.getExtractionFn();
    final int dimIndex = desc.getIndex();
    // maxId is used in concert with getLastRowIndex() in IncrementalIndex to ensure that callers do not encounter
    // rows that contain IDs over the initially-reported cardinality. The main idea is that IncrementalIndex establishes
    // a watermark at the time a cursor is created, and doesn't allow the cursor to walk past that watermark.
    // 
    // Additionally, this selector explicitly blocks knowledge of IDs past maxId that may occur from other causes
    // (for example: nulls getting generated for empty arrays, or calls to lookupId).
    final int maxId = getCardinality();
    class IndexerDimensionSelector implements DimensionSelector, IdLookup {

        private final ArrayBasedIndexedInts indexedInts = new ArrayBasedIndexedInts();

        @Nullable
        @MonotonicNonNull
        private int[] nullIdIntArray;

        @Override
        public IndexedInts getRow() {
            final Object[] dims = currEntry.get().getDims();
            int[] indices;
            if (dimIndex < dims.length) {
                indices = (int[]) dims[dimIndex];
            } else {
                indices = null;
            }
            int[] row = null;
            int rowSize = 0;
            // usually due to currEntry's rowIndex is smaller than the row's rowIndex in which this dim first appears
            if (indices == null || indices.length == 0) {
                if (hasMultipleValues) {
                    row = IntArrays.EMPTY_ARRAY;
                    rowSize = 0;
                } else {
                    final int nullId = getEncodedValue(null, false);
                    if (nullId >= 0 && nullId < maxId) {
                        // null was added to the dictionary before this selector was created; return its ID.
                        if (nullIdIntArray == null) {
                            nullIdIntArray = new int[] { nullId };
                        }
                        row = nullIdIntArray;
                        rowSize = 1;
                    } else {
                        // null doesn't exist in the dictionary; return an empty array.
                        // Choose to use ArrayBasedIndexedInts later, instead of special "empty" IndexedInts, for monomorphism
                        row = IntArrays.EMPTY_ARRAY;
                        rowSize = 0;
                    }
                }
            }
            if (row == null && indices != null && indices.length > 0) {
                row = indices;
                rowSize = indices.length;
            }
            indexedInts.setValues(row, rowSize);
            return indexedInts;
        }

        @Override
        public ValueMatcher makeValueMatcher(final String value) {
            if (extractionFn == null) {
                final int valueId = lookupId(value);
                if (valueId >= 0 || value == null) {
                    return new ValueMatcher() {

                        @Override
                        public boolean matches() {
                            Object[] dims = currEntry.get().getDims();
                            if (dimIndex >= dims.length) {
                                return value == null;
                            }
                            int[] dimsInt = (int[]) dims[dimIndex];
                            if (dimsInt == null || dimsInt.length == 0) {
                                return value == null;
                            }
                            for (int id : dimsInt) {
                                if (id == valueId) {
                                    return true;
                                }
                            }
                            return false;
                        }

                        @Override
                        public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
                        // nothing to inspect
                        }
                    };
                } 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(maxId);
            final BitSet matchingIds = new BitSet(maxId);
            final boolean matchNull = predicate.apply(null);
            // Lazy matcher; only check an id if matches() is called.
            return new ValueMatcher() {

                @Override
                public boolean matches() {
                    Object[] dims = currEntry.get().getDims();
                    if (dimIndex >= dims.length) {
                        return matchNull;
                    }
                    int[] dimsInt = (int[]) dims[dimIndex];
                    if (dimsInt == null || dimsInt.length == 0) {
                        return matchNull;
                    }
                    for (int id : dimsInt) {
                        if (checkedIds.get(id)) {
                            if (matchingIds.get(id)) {
                                return true;
                            }
                        } else {
                            final boolean matches = predicate.apply(lookupName(id));
                            checkedIds.set(id);
                            if (matches) {
                                matchingIds.set(id);
                                return true;
                            }
                        }
                    }
                    return false;
                }

                @Override
                public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
                // nothing to inspect
                }
            };
        }

        @Override
        public int getValueCardinality() {
            return maxId;
        }

        @Override
        public String lookupName(int id) {
            if (id >= maxId) {
                // Sanity check; IDs beyond maxId should not be known to callers. (See comment above.)
                throw new ISE("id[%d] >= maxId[%d]", id, maxId);
            }
            final String strValue = getActualValue(id, false);
            return extractionFn == null ? strValue : extractionFn.apply(strValue);
        }

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

        @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");
            }
            final int id = getEncodedValue(name, false);
            if (id < maxId) {
                return id;
            } else {
                // doesn't exist.
                return DimensionDictionary.ABSENT_VALUE_ID;
            }
        }

        @SuppressWarnings("deprecation")
        @Nullable
        @Override
        public Object getObject() {
            IncrementalIndexRow key = currEntry.get();
            if (key == null) {
                return null;
            }
            Object[] dims = key.getDims();
            if (dimIndex >= dims.length) {
                return null;
            }
            return convertUnsortedEncodedKeyComponentToActualList((int[]) dims[dimIndex]);
        }

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

        @Override
        public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
        // nothing to inspect
        }
    }
    return new IndexerDimensionSelector();
}
Also used : ValueMatcher(org.apache.druid.query.filter.ValueMatcher) BooleanValueMatcher(org.apache.druid.segment.filter.BooleanValueMatcher) BitSet(java.util.BitSet) RuntimeShapeInspector(org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector) Predicate(com.google.common.base.Predicate) ExtractionFn(org.apache.druid.query.extraction.ExtractionFn) IncrementalIndexRow(org.apache.druid.segment.incremental.IncrementalIndexRow) ArrayBasedIndexedInts(org.apache.druid.segment.data.ArrayBasedIndexedInts) ISE(org.apache.druid.java.util.common.ISE)

Example 24 with ValueMatcher

use of org.apache.druid.query.filter.ValueMatcher in project druid by druid-io.

the class FilteredAggregatorTest method makeColumnSelector.

private ColumnSelectorFactory makeColumnSelector(final TestFloatColumnSelector selector) {
    return new ColumnSelectorFactory() {

        @Override
        public DimensionSelector makeDimensionSelector(DimensionSpec dimensionSpec) {
            final String dimensionName = dimensionSpec.getDimension();
            if ("dim".equals(dimensionName)) {
                return dimensionSpec.decorate(new AbstractDimensionSelector() {

                    @Override
                    public IndexedInts getRow() {
                        SingleIndexedInt row = new SingleIndexedInt();
                        if (selector.getIndex() % 3 == 2) {
                            row.setValue(1);
                        } else {
                            row.setValue(0);
                        }
                        return row;
                    }

                    @Override
                    public ValueMatcher makeValueMatcher(String value) {
                        return DimensionSelectorUtils.makeValueMatcherGeneric(this, value);
                    }

                    @Override
                    public ValueMatcher makeValueMatcher(Predicate<String> predicate) {
                        return DimensionSelectorUtils.makeValueMatcherGeneric(this, predicate);
                    }

                    @Override
                    public int getValueCardinality() {
                        return 2;
                    }

                    @Override
                    public String lookupName(int id) {
                        switch(id) {
                            case 0:
                                return "a";
                            case 1:
                                return "b";
                            default:
                                throw new IllegalArgumentException();
                        }
                    }

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

                    @Nullable
                    @Override
                    public IdLookup idLookup() {
                        return new IdLookup() {

                            @Override
                            public int lookupId(String name) {
                                switch(name) {
                                    case "a":
                                        return 0;
                                    case "b":
                                        return 1;
                                    default:
                                        throw new IllegalArgumentException();
                                }
                            }
                        };
                    }

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

                    @Override
                    public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
                    // Don't care about runtime shape in tests
                    }
                });
            } else {
                throw new UnsupportedOperationException();
            }
        }

        @Override
        public ColumnValueSelector<?> makeColumnValueSelector(String columnName) {
            if ("value".equals(columnName)) {
                return selector;
            } else {
                throw new UnsupportedOperationException();
            }
        }

        @Override
        public ColumnCapabilities getColumnCapabilities(String columnName) {
            ColumnCapabilitiesImpl caps;
            if ("value".equals(columnName)) {
                caps = new ColumnCapabilitiesImpl();
                caps.setType(ColumnType.FLOAT);
                caps.setDictionaryEncoded(false);
                caps.setHasBitmapIndexes(false);
            } else {
                caps = new ColumnCapabilitiesImpl();
                caps.setType(ColumnType.STRING);
                caps.setDictionaryEncoded(true);
                caps.setHasBitmapIndexes(true);
            }
            return caps;
        }
    };
}
Also used : DimensionSpec(org.apache.druid.query.dimension.DimensionSpec) ColumnSelectorFactory(org.apache.druid.segment.ColumnSelectorFactory) ValueMatcher(org.apache.druid.query.filter.ValueMatcher) SingleIndexedInt(org.apache.druid.segment.data.SingleIndexedInt) RuntimeShapeInspector(org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector) IdLookup(org.apache.druid.segment.IdLookup) AbstractDimensionSelector(org.apache.druid.segment.AbstractDimensionSelector) IndexedInts(org.apache.druid.segment.data.IndexedInts) Nullable(javax.annotation.Nullable) ColumnCapabilitiesImpl(org.apache.druid.segment.column.ColumnCapabilitiesImpl)

Example 25 with ValueMatcher

use of org.apache.druid.query.filter.ValueMatcher in project druid by druid-io.

the class AndFilter method makeMatcher.

@Override
public ValueMatcher makeMatcher(ColumnSelectorFactory factory) {
    final ValueMatcher[] matchers = new ValueMatcher[filters.size()];
    int i = 0;
    for (Filter filter : filters) {
        matchers[i++] = filter.makeMatcher(factory);
    }
    return makeMatcher(matchers);
}
Also used : VectorValueMatcher(org.apache.druid.query.filter.vector.VectorValueMatcher) ValueMatcher(org.apache.druid.query.filter.ValueMatcher) BaseVectorValueMatcher(org.apache.druid.query.filter.vector.BaseVectorValueMatcher) BooleanFilter(org.apache.druid.query.filter.BooleanFilter) Filter(org.apache.druid.query.filter.Filter)

Aggregations

ValueMatcher (org.apache.druid.query.filter.ValueMatcher)59 InitializedNullHandlingTest (org.apache.druid.testing.InitializedNullHandlingTest)33 Test (org.junit.Test)33 RuntimeShapeInspector (org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector)19 IndexedInts (org.apache.druid.segment.data.IndexedInts)11 BooleanValueMatcher (org.apache.druid.segment.filter.BooleanValueMatcher)9 VectorValueMatcher (org.apache.druid.query.filter.vector.VectorValueMatcher)7 BaseVectorValueMatcher (org.apache.druid.query.filter.vector.BaseVectorValueMatcher)6 ArrayList (java.util.ArrayList)5 BitSet (java.util.BitSet)5 Nullable (javax.annotation.Nullable)5 Filter (org.apache.druid.query.filter.Filter)5 DimensionSelector (org.apache.druid.segment.DimensionSelector)5 ArrayBasedIndexedInts (org.apache.druid.segment.data.ArrayBasedIndexedInts)5 Predicate (com.google.common.base.Predicate)4 IdLookup (org.apache.druid.segment.IdLookup)4 DefaultDimensionSpec (org.apache.druid.query.dimension.DefaultDimensionSpec)3 BooleanFilter (org.apache.druid.query.filter.BooleanFilter)3 ConstantDimensionSelector (org.apache.druid.segment.ConstantDimensionSelector)3 ConstantMultiValueDimensionSelector (org.apache.druid.segment.ConstantMultiValueDimensionSelector)3