in processing/src/main/java/org/apache/druid/segment/nested/NestedFieldDictionaryEncodedColumn.java [529:750]
public ColumnValueSelector<?> makeColumnValueSelector(ReadableOffset offset)
{
if (singleType != null) {
// this null handling stuff is copied from elsewhere, and also copied in basically all of the
// numerical column selectors, there is probably some base structure that can be extracted...
if (Types.is(singleType, ValueType.LONG)) {
return new LongColumnSelector()
{
private PeekableIntIterator nullIterator = nullBitmap.peekableIterator();
private int nullMark = -1;
private int offsetMark = -1;
@Override
public long getLong()
{
return longsColumn.get(offset.getOffset());
}
@Override
public void inspectRuntimeShape(RuntimeShapeInspector inspector)
{
inspector.visit("longColumn", longsColumn);
inspector.visit("nullBitmap", nullBitmap);
}
@Override
public boolean isNull()
{
final int i = offset.getOffset();
if (i < offsetMark) {
// offset was reset, reset iterator state
nullMark = -1;
nullIterator = nullBitmap.peekableIterator();
}
offsetMark = i;
if (nullMark < i) {
nullIterator.advanceIfNeeded(offsetMark);
if (nullIterator.hasNext()) {
nullMark = nullIterator.next();
}
}
return nullMark == offsetMark;
}
};
} else if (Types.is(singleType, ValueType.DOUBLE)) {
return new DoubleColumnSelector()
{
private PeekableIntIterator nullIterator = nullBitmap.peekableIterator();
private int nullMark = -1;
private int offsetMark = -1;
@Override
public double getDouble()
{
return doublesColumn.get(offset.getOffset());
}
@Override
public void inspectRuntimeShape(RuntimeShapeInspector inspector)
{
inspector.visit("doubleColumn", doublesColumn);
inspector.visit("nullBitmap", nullBitmap);
}
@Override
public boolean isNull()
{
final int i = offset.getOffset();
if (i < offsetMark) {
// offset was reset, reset iterator state
nullMark = -1;
nullIterator = nullBitmap.peekableIterator();
}
offsetMark = i;
if (nullMark < i) {
nullIterator.advanceIfNeeded(offsetMark);
if (nullIterator.hasNext()) {
nullMark = nullIterator.next();
}
}
return nullMark == offsetMark;
}
};
}
}
if (singleType == null || singleType.isArray()) {
return new ColumnValueSelector<>()
{
private PeekableIntIterator nullIterator = nullBitmap.peekableIterator();
private int nullMark = -1;
private int offsetMark = -1;
@Nullable
@Override
public Object getObject()
{
final int localId = column.get(offset.getOffset());
final int globalId = dictionary.get(localId);
if (globalId < adjustArrayId) {
return lookupGlobalScalarObject(globalId);
} else {
int[] arr = globalArrayDictionary.get(globalId - adjustArrayId);
if (arr == null) {
return null;
}
final Object[] array = new Object[arr.length];
for (int i = 0; i < arr.length; i++) {
array[i] = lookupGlobalScalarObject(arr[i]);
}
return array;
}
}
@Override
public float getFloat()
{
final int localId = column.get(offset.getOffset());
final int globalId = dictionary.get(localId);
if (globalId == 0) {
// zero
return 0f;
} else if (globalId < adjustLongId) {
// try to convert string to float
Float f = Floats.tryParse(StringUtils.fromUtf8(globalDictionary.get(globalId)));
return f == null ? 0f : f;
} else if (globalId < adjustDoubleId) {
return globalLongDictionary.get(globalId - adjustLongId).floatValue();
} else {
return globalDoubleDictionary.get(globalId - adjustDoubleId).floatValue();
}
}
@Override
public double getDouble()
{
final int localId = column.get(offset.getOffset());
final int globalId = dictionary.get(localId);
if (globalId == 0) {
// zero
return 0.0;
} else if (globalId < adjustLongId) {
// try to convert string to double
Double d = Doubles.tryParse(StringUtils.fromUtf8(globalDictionary.get(globalId)));
return d == null ? 0.0 : d;
} else if (globalId < adjustDoubleId) {
return globalLongDictionary.get(globalId - adjustLongId).doubleValue();
} else {
return globalDoubleDictionary.get(globalId - adjustDoubleId);
}
}
@Override
public long getLong()
{
final int localId = column.get(offset.getOffset());
final int globalId = dictionary.get(localId);
if (globalId == 0) {
// zero
return 0L;
} else if (globalId < adjustLongId) {
// try to convert string to long
Long l = GuavaUtils.tryParseLong(StringUtils.fromUtf8(globalDictionary.get(globalId)));
return l == null ? 0L : l;
} else if (globalId < adjustDoubleId) {
return globalLongDictionary.get(globalId - adjustLongId);
} else {
return globalDoubleDictionary.get(globalId - adjustDoubleId).longValue();
}
}
@Override
public boolean isNull()
{
final int i = offset.getOffset();
if (i < offsetMark) {
// offset was reset, reset iterator state
nullMark = -1;
nullIterator = nullBitmap.peekableIterator();
}
offsetMark = i;
if (nullMark < i) {
nullIterator.advanceIfNeeded(offsetMark);
if (nullIterator.hasNext()) {
nullMark = nullIterator.next();
}
}
if (nullMark == offsetMark) {
return true;
}
final int localId = column.get(offset.getOffset());
final int globalId = dictionary.get(localId);
// zero is always null
if (globalId == 0) {
return true;
} else if (globalId < adjustLongId) {
final String value = StringUtils.fromUtf8Nullable(globalDictionary.get(globalId));
return GuavaUtils.tryParseLong(value) == null && Doubles.tryParse(value) == null;
}
// if id is less than array ids, it is definitely a number and not null (since null is 0)
return globalId >= adjustArrayId;
}
@Override
public Class<?> classOfObject()
{
return Object.class;
}
@Override
public void inspectRuntimeShape(RuntimeShapeInspector inspector)
{
inspector.visit("longColumn", longsColumn);
inspector.visit("nullBitmap", nullBitmap);
}
};
}
// single type strings, use a dimension selector
return makeDimensionSelector(offset, null);
}