Search in sources :

Example 1 with ArrayBasedIndexedInts

use of org.apache.druid.segment.data.ArrayBasedIndexedInts in project druid by druid-io.

the class LookupJoinMatcherTest method testMatchEmptyRow.

@Test
public void testMatchEmptyRow() {
    ArrayBasedIndexedInts row = new ArrayBasedIndexedInts(new int[] {});
    Mockito.doReturn(dimensionSelector).when(leftSelectorFactory).makeDimensionSelector(ArgumentMatchers.any(DimensionSpec.class));
    Mockito.doReturn(row).when(dimensionSelector).getRow();
    JoinConditionAnalysis condition = JoinConditionAnalysis.forExpression(StringUtils.format("\"%sk\" == foo", PREFIX), PREFIX, ExprMacroTable.nil());
    target = LookupJoinMatcher.create(extractor, leftSelectorFactory, condition, true);
    target.matchCondition();
    Assert.assertFalse(target.hasMatch());
}
Also used : DefaultDimensionSpec(org.apache.druid.query.dimension.DefaultDimensionSpec) DimensionSpec(org.apache.druid.query.dimension.DimensionSpec) ArrayBasedIndexedInts(org.apache.druid.segment.data.ArrayBasedIndexedInts) JoinConditionAnalysis(org.apache.druid.segment.join.JoinConditionAnalysis) Test(org.junit.Test)

Example 2 with ArrayBasedIndexedInts

use of org.apache.druid.segment.data.ArrayBasedIndexedInts 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 3 with ArrayBasedIndexedInts

use of org.apache.druid.segment.data.ArrayBasedIndexedInts in project druid by druid-io.

the class LookupJoinMatcherTest method testMatchMultiValuedRowShouldThrowException.

@Test(expected = QueryUnsupportedException.class)
public void testMatchMultiValuedRowShouldThrowException() {
    ArrayBasedIndexedInts row = new ArrayBasedIndexedInts(new int[] { 2, 4, 6 });
    Mockito.doReturn(dimensionSelector).when(leftSelectorFactory).makeDimensionSelector(ArgumentMatchers.any(DimensionSpec.class));
    Mockito.doReturn(row).when(dimensionSelector).getRow();
    JoinConditionAnalysis condition = JoinConditionAnalysis.forExpression(StringUtils.format("\"%sk\" == foo", PREFIX), PREFIX, ExprMacroTable.nil());
    target = LookupJoinMatcher.create(extractor, leftSelectorFactory, condition, true);
    // Test match should throw exception
    target.matchCondition();
}
Also used : DefaultDimensionSpec(org.apache.druid.query.dimension.DefaultDimensionSpec) DimensionSpec(org.apache.druid.query.dimension.DimensionSpec) ArrayBasedIndexedInts(org.apache.druid.segment.data.ArrayBasedIndexedInts) JoinConditionAnalysis(org.apache.druid.segment.join.JoinConditionAnalysis) Test(org.junit.Test)

Example 4 with ArrayBasedIndexedInts

use of org.apache.druid.segment.data.ArrayBasedIndexedInts in project druid by druid-io.

the class DictionaryBuildingStringGroupByColumnSelectorStrategy method initColumnValues.

@Override
public void initColumnValues(ColumnValueSelector selector, int columnIndex, Object[] valuess) {
    final DimensionSelector dimSelector = (DimensionSelector) selector;
    final IndexedInts row = dimSelector.getRow();
    ArrayBasedIndexedInts newRow = (ArrayBasedIndexedInts) valuess[columnIndex];
    if (newRow == null) {
        newRow = new ArrayBasedIndexedInts();
        valuess[columnIndex] = newRow;
    }
    int rowSize = row.size();
    newRow.ensureSize(rowSize);
    for (int i = 0; i < rowSize; i++) {
        final String value = dimSelector.lookupName(row.get(i));
        final int dictId = reverseDictionary.getInt(value);
        if (dictId < 0) {
            dictionary.add(value);
            reverseDictionary.put(value, nextId);
            newRow.setValue(i, nextId);
            nextId++;
        } else {
            newRow.setValue(i, dictId);
        }
    }
    newRow.setSize(rowSize);
}
Also used : DimensionSelector(org.apache.druid.segment.DimensionSelector) ArrayBasedIndexedInts(org.apache.druid.segment.data.ArrayBasedIndexedInts) IndexedInts(org.apache.druid.segment.data.IndexedInts) ArrayBasedIndexedInts(org.apache.druid.segment.data.ArrayBasedIndexedInts)

Example 5 with ArrayBasedIndexedInts

use of org.apache.druid.segment.data.ArrayBasedIndexedInts in project druid by druid-io.

the class AlwaysTwoVectorizedVirtualColumn method makeMultiValueVectorDimensionSelector.

@Override
public MultiValueDimensionVectorSelector makeMultiValueVectorDimensionSelector(DimensionSpec dimensionSpec, VectorColumnSelectorFactory factory) {
    Assert.assertEquals(outputName, dimensionSpec.getOutputName());
    final IndexedInts[] rowVector = new IndexedInts[factory.getReadableVectorInspector().getMaxVectorSize()];
    Arrays.fill(rowVector, new ArrayBasedIndexedInts(new int[] { 0, 0 }));
    return new MultiValueDimensionVectorSelector() {

        private final VectorSizeInspector inspector = factory.getReadableVectorInspector();

        @Override
        public IndexedInts[] getRowVector() {
            return rowVector;
        }

        @Override
        public int getValueCardinality() {
            return dictionaryEncoded ? 1 : CARDINALITY_UNKNOWN;
        }

        @Nullable
        @Override
        public String lookupName(int id) {
            return "2";
        }

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

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

        @Override
        public int getMaxVectorSize() {
            return inspector.getMaxVectorSize();
        }

        @Override
        public int getCurrentVectorSize() {
            return inspector.getCurrentVectorSize();
        }
    };
}
Also used : MultiValueDimensionVectorSelector(org.apache.druid.segment.vector.MultiValueDimensionVectorSelector) ArrayBasedIndexedInts(org.apache.druid.segment.data.ArrayBasedIndexedInts) IndexedInts(org.apache.druid.segment.data.IndexedInts) ArrayBasedIndexedInts(org.apache.druid.segment.data.ArrayBasedIndexedInts) VectorSizeInspector(org.apache.druid.segment.vector.VectorSizeInspector)

Aggregations

ArrayBasedIndexedInts (org.apache.druid.segment.data.ArrayBasedIndexedInts)6 IndexedInts (org.apache.druid.segment.data.IndexedInts)3 Test (org.junit.Test)3 DefaultDimensionSpec (org.apache.druid.query.dimension.DefaultDimensionSpec)2 DimensionSpec (org.apache.druid.query.dimension.DimensionSpec)2 JoinConditionAnalysis (org.apache.druid.segment.join.JoinConditionAnalysis)2 MultiValueDimensionVectorSelector (org.apache.druid.segment.vector.MultiValueDimensionVectorSelector)2 Predicate (com.google.common.base.Predicate)1 BitSet (java.util.BitSet)1 Nullable (javax.annotation.Nullable)1 ISE (org.apache.druid.java.util.common.ISE)1 MultiValueStringCardinalityVectorProcessor (org.apache.druid.query.aggregation.cardinality.vector.MultiValueStringCardinalityVectorProcessor)1 ExtractionFn (org.apache.druid.query.extraction.ExtractionFn)1 ValueMatcher (org.apache.druid.query.filter.ValueMatcher)1 RuntimeShapeInspector (org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector)1 DimensionSelector (org.apache.druid.segment.DimensionSelector)1 IdLookup (org.apache.druid.segment.IdLookup)1 BooleanValueMatcher (org.apache.druid.segment.filter.BooleanValueMatcher)1 IncrementalIndexRow (org.apache.druid.segment.incremental.IncrementalIndexRow)1 VectorSizeInspector (org.apache.druid.segment.vector.VectorSizeInspector)1