in processing/src/main/java/org/apache/druid/segment/nested/VariantColumn.java [379:618]
public DimensionSelector makeDimensionSelector(
ReadableOffset offset,
@Nullable ExtractionFn extractionFn
)
{
if (variantTypes == null && logicalType.isArray()) {
throw new IAE("Dimension selector is currently unsupported for [%s]", logicalType);
}
// copy everywhere all the time
class StringDimensionSelector extends AbstractDimensionSelector
implements SingleValueHistoricalDimensionSelector, IdLookup
{
private final SingleIndexedInt row = new SingleIndexedInt();
@Override
public IndexedInts getRow()
{
row.setValue(getRowValue());
return row;
}
public int getRowValue()
{
return encodedValueColumn.get(offset.getOffset());
}
@Override
public float getFloat()
{
final int id = getRowValue();
if (id == 0) {
// zero
return 0f;
} else if (id < adjustLongId) {
// try to convert string to float
Float f = Floats.tryParse(StringUtils.fromUtf8(stringDictionary.get(id)));
return f == null ? 0f : f;
} else if (id < adjustDoubleId) {
return longDictionary.get(id - adjustLongId).floatValue();
} else {
return doubleDictionary.get(id - adjustDoubleId).floatValue();
}
}
@Override
public double getDouble()
{
final int id = getRowValue();
if (id == 0) {
// zero
return 0.0;
} else if (id < adjustLongId) {
// try to convert string to double
Double d = Doubles.tryParse(StringUtils.fromUtf8(stringDictionary.get(id)));
return d == null ? 0.0 : d;
} else if (id < adjustDoubleId) {
return longDictionary.get(id - adjustLongId).doubleValue();
} else {
return doubleDictionary.get(id - adjustDoubleId);
}
}
@Override
public long getLong()
{
final int id = getRowValue();
if (id == 0) {
// zero
return 0L;
} else if (id < adjustLongId) {
// try to convert string to long
Long l = GuavaUtils.tryParseLong(StringUtils.fromUtf8(stringDictionary.get(id)));
return l == null ? 0L : l;
} else if (id < adjustDoubleId) {
return longDictionary.get(id - adjustLongId);
} else {
return doubleDictionary.get(id - adjustDoubleId).longValue();
}
}
@Override
public boolean isNull()
{
if (getRowValue() == 0) {
return true;
}
return DimensionHandlerUtils.isNumericNull(getObject());
}
@Override
public IndexedInts getRow(int offset)
{
row.setValue(getRowValue(offset));
return row;
}
@Override
public int getRowValue(int offset)
{
return encodedValueColumn.get(offset);
}
@Override
public ValueMatcher makeValueMatcher(final @Nullable String value)
{
if (extractionFn == null) {
final IntSet valueIds = VariantColumn.this.lookupIds(value);
if (valueIds.size() > 0) {
return new ValueMatcher()
{
@Override
public boolean matches(boolean includeUnknown)
{
final int rowId = getRowValue();
// null is always 0
return (includeUnknown && rowId == 0) || valueIds.contains(getRowValue());
}
@Override
public void inspectRuntimeShape(RuntimeShapeInspector inspector)
{
inspector.visit("column", VariantColumn.this);
}
};
} else {
return new ValueMatcher()
{
@Override
public boolean matches(boolean includeUnknown)
{
// null is always 0
return includeUnknown && getRowValue() == 0;
}
@Override
public void inspectRuntimeShape(RuntimeShapeInspector inspector)
{
inspector.visit("column", VariantColumn.this);
}
};
}
} else {
// Employ caching BitSet optimization
return makeValueMatcher(StringPredicateDruidPredicateFactory.equalTo(value));
}
}
@Override
public ValueMatcher makeValueMatcher(final DruidPredicateFactory predicateFactory)
{
final BitSet checkedIds = new BitSet(getCardinality());
final BitSet matchingIds = new BitSet(getCardinality());
final DruidObjectPredicate<String> predicate = predicateFactory.makeStringPredicate();
// Lazy matcher; only check an id if matches() is called.
return new ValueMatcher()
{
@Override
public boolean matches(boolean includeUnknown)
{
final int id = getRowValue();
if (checkedIds.get(id)) {
return matchingIds.get(id);
} else {
final boolean matches = predicate.apply(lookupName(id)).matches(includeUnknown);
checkedIds.set(id);
if (matches) {
matchingIds.set(id);
}
return matches;
}
}
@Override
public void inspectRuntimeShape(RuntimeShapeInspector inspector)
{
inspector.visit("column", VariantColumn.this);
}
};
}
@Override
public Object getObject()
{
return VariantColumn.this.lookupName(getRowValue());
}
@Override
public Class classOfObject()
{
return String.class;
}
@Override
public void inspectRuntimeShape(RuntimeShapeInspector inspector)
{
inspector.visit("column", encodedValueColumn);
inspector.visit("offset", offset);
inspector.visit("extractionFn", extractionFn);
}
@Override
public int getValueCardinality()
{
return getCardinality();
}
@Override
public String lookupName(int id)
{
final String value = VariantColumn.this.lookupName(id);
return extractionFn == null ? value : extractionFn.apply(value);
}
@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) {
return VariantColumn.this.lookupId(name);
}
throw new UnsupportedOperationException("cannot perform lookup when applying an extraction function");
}
}
return new StringDimensionSelector();
}