use of org.apache.druid.segment.IdLookup in project druid by druid-io.
the class VectorValueMatcherColumnProcessorFactoryTest method testSingleValueStringOneCardinalityBooleanMatcherIfNullAndNameLookupNotPossible.
@Test
public void testSingleValueStringOneCardinalityBooleanMatcherIfNullAndNameLookupNotPossible() {
// if name lookup not possible in advance, use normal path, even if cardinality 1
IdLookup lookup = EasyMock.createMock(IdLookup.class);
SingleValueDimensionVectorSelector selector = EasyMock.createMock(SingleValueDimensionVectorSelector.class);
EasyMock.expect(selector.getCurrentVectorSize()).andReturn(CURRENT_SIZE).anyTimes();
EasyMock.expect(selector.getMaxVectorSize()).andReturn(VECTOR_SIZE).anyTimes();
EasyMock.expect(selector.getValueCardinality()).andReturn(1).anyTimes();
EasyMock.expect(selector.nameLookupPossibleInAdvance()).andReturn(false).anyTimes();
EasyMock.expect(selector.idLookup()).andReturn(lookup).anyTimes();
EasyMock.expect(lookup.lookupId("any value")).andReturn(1).anyTimes();
EasyMock.expect(lookup.lookupId(null)).andReturn(0).anyTimes();
EasyMock.replay(selector, lookup);
VectorValueMatcherFactory matcherFactory = VectorValueMatcherColumnProcessorFactory.instance().makeSingleValueDimensionProcessor(new ColumnCapabilitiesImpl().setType(ColumnType.STRING).setHasMultipleValues(false).setHasBitmapIndexes(true).setDictionaryValuesUnique(true).setDictionaryValuesSorted(true).setDictionaryEncoded(true), selector);
Assert.assertTrue(matcherFactory instanceof SingleValueStringVectorValueMatcher);
VectorValueMatcher matcher = matcherFactory.makeMatcher("any value");
Assert.assertFalse(matcher instanceof BooleanVectorValueMatcher);
Assert.assertEquals(VECTOR_SIZE, matcher.getMaxVectorSize());
Assert.assertEquals(CURRENT_SIZE, matcher.getCurrentVectorSize());
EasyMock.verify(selector, lookup);
}
use of org.apache.druid.segment.IdLookup in project druid by druid-io.
the class VectorValueMatcherColumnProcessorFactoryTest method testSingleValueString.
@Test
public void testSingleValueString() {
IdLookup lookup = EasyMock.createMock(IdLookup.class);
SingleValueDimensionVectorSelector selector = EasyMock.createMock(SingleValueDimensionVectorSelector.class);
EasyMock.expect(selector.getCurrentVectorSize()).andReturn(CURRENT_SIZE).anyTimes();
EasyMock.expect(selector.getMaxVectorSize()).andReturn(VECTOR_SIZE).anyTimes();
EasyMock.expect(selector.getValueCardinality()).andReturn(1024).anyTimes();
EasyMock.expect(selector.nameLookupPossibleInAdvance()).andReturn(false).anyTimes();
EasyMock.expect(selector.idLookup()).andReturn(lookup).anyTimes();
EasyMock.expect(lookup.lookupId("any value")).andReturn(1).anyTimes();
EasyMock.expect(lookup.lookupId("another value")).andReturn(-1).anyTimes();
EasyMock.replay(selector, lookup);
VectorValueMatcherFactory matcherFactory = VectorValueMatcherColumnProcessorFactory.instance().makeSingleValueDimensionProcessor(new ColumnCapabilitiesImpl().setType(ColumnType.STRING).setHasMultipleValues(false).setHasBitmapIndexes(true).setDictionaryValuesUnique(true).setDictionaryValuesSorted(true).setDictionaryEncoded(true), selector);
Assert.assertTrue(matcherFactory instanceof SingleValueStringVectorValueMatcher);
// value exists in column nonboolean matcher
VectorValueMatcher matcher = matcherFactory.makeMatcher("any value");
Assert.assertFalse(matcher instanceof BooleanVectorValueMatcher);
Assert.assertEquals(VECTOR_SIZE, matcher.getMaxVectorSize());
Assert.assertEquals(CURRENT_SIZE, matcher.getCurrentVectorSize());
// value not exist in dictionary uses boolean matcher
VectorValueMatcher booleanMatcher = matcherFactory.makeMatcher("another value");
Assert.assertTrue(booleanMatcher instanceof BooleanVectorValueMatcher);
Assert.assertEquals(VECTOR_SIZE, booleanMatcher.getMaxVectorSize());
Assert.assertEquals(CURRENT_SIZE, booleanMatcher.getCurrentVectorSize());
EasyMock.verify(selector, lookup);
}
use of org.apache.druid.segment.IdLookup 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.IdLookup in project druid by druid-io.
the class CardinalityVectorAggregatorTest method testAggregateSingleValueString.
@Test
public void testAggregateSingleValueString() {
final int[] ids = { 1, 2, 2, 3, 3, 3, 0 };
final String[] dict = { null, "abc", "def", "foo" };
final CardinalityVectorAggregator aggregator = new CardinalityVectorAggregator(Collections.singletonList(new SingleValueStringCardinalityVectorProcessor(new SingleValueDimensionVectorSelector() {
@Override
public int[] getRowVector() {
return ids;
}
@Override
public int getValueCardinality() {
return dict.length;
}
@Nullable
@Override
public String lookupName(int id) {
return dict[id];
}
@Override
public boolean nameLookupPossibleInAdvance() {
return true;
}
@Nullable
@Override
public IdLookup idLookup() {
return null;
}
@Override
public int getMaxVectorSize() {
return ids.length;
}
@Override
public int getCurrentVectorSize() {
return ids.length;
}
})));
testAggregate(aggregator, ids.length, NullHandling.replaceWithDefault() ? 4 : 3);
}
use of org.apache.druid.segment.IdLookup in project druid by druid-io.
the class ExpressionVirtualColumnTest method testMultiObjectSelectorMakesRightSelector.
@Test
public void testMultiObjectSelectorMakesRightSelector() {
DimensionSpec spec = new DefaultDimensionSpec("expr", "expr");
// do some ugly faking to test if SingleStringInputDeferredEvaluationExpressionDimensionSelector is created for multi-value expressions when possible
ColumnSelectorFactory factory = new ColumnSelectorFactory() {
@Override
public DimensionSelector makeDimensionSelector(DimensionSpec dimensionSpec) {
DimensionSelector delegate = COLUMN_SELECTOR_FACTORY.makeDimensionSelector(dimensionSpec);
DimensionSelector faker = new DimensionSelector() {
@Override
public IndexedInts getRow() {
return delegate.getRow();
}
@Override
public ValueMatcher makeValueMatcher(@Nullable String value) {
return delegate.makeValueMatcher(value);
}
@Override
public ValueMatcher makeValueMatcher(Predicate<String> predicate) {
return delegate.makeValueMatcher(predicate);
}
@Override
public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
delegate.inspectRuntimeShape(inspector);
}
@Nullable
@Override
public Object getObject() {
return delegate.getObject();
}
@Override
public Class<?> classOfObject() {
return delegate.classOfObject();
}
@Override
public int getValueCardinality() {
// value doesn't matter as long as not CARDINALITY_UNKNOWN
return 3;
}
@Nullable
@Override
public String lookupName(int id) {
return null;
}
@Override
public boolean nameLookupPossibleInAdvance() {
// fake this so when SingleStringInputDeferredEvaluationExpressionDimensionSelector it doesn't explode
return true;
}
@Nullable
@Override
public IdLookup idLookup() {
return name -> 0;
}
};
return faker;
}
@Override
public ColumnValueSelector makeColumnValueSelector(String columnName) {
return COLUMN_SELECTOR_FACTORY.makeColumnValueSelector(columnName);
}
@Nullable
@Override
public ColumnCapabilities getColumnCapabilities(String column) {
return new ColumnCapabilitiesImpl().setType(ColumnType.STRING).setHasMultipleValues(true).setDictionaryEncoded(true);
}
};
final BaseObjectColumnValueSelector selectorImplicit = SCALE_LIST_SELF_IMPLICIT.makeDimensionSelector(spec, factory);
final BaseObjectColumnValueSelector selectorExplicit = SCALE_LIST_SELF_EXPLICIT.makeDimensionSelector(spec, factory);
Assert.assertTrue(selectorImplicit instanceof SingleStringInputDeferredEvaluationExpressionDimensionSelector);
Assert.assertTrue(selectorExplicit instanceof ExpressionMultiValueDimensionSelector);
}
Aggregations