in processing/src/main/java/org/apache/druid/segment/virtual/NestedFieldVirtualColumn.java [642:1155]
public VectorValueSelector makeVectorValueSelector(
String columnName,
ColumnSelector columnSelector,
ReadableVectorOffset offset
)
{
ColumnHolder holder = columnSelector.getColumnHolder(fieldSpec.columnName);
if (holder == null) {
return NilVectorSelector.create(offset);
}
BaseColumn theColumn = holder.getColumn();
if (!(theColumn instanceof NestedDataComplexColumn)) {
if (fieldSpec.parts.isEmpty()) {
if (theColumn instanceof DictionaryEncodedColumn) {
final VectorObjectSelector delegate = theColumn.makeVectorObjectSelector(offset);
if (fieldSpec.expectedType != null && fieldSpec.expectedType.is(ValueType.LONG)) {
return new BaseLongVectorValueSelector(offset)
{
private int currentOffsetId = ReadableVectorInspector.NULL_ID;
private final long[] longs = new long[delegate.getMaxVectorSize()];
@Nullable
private boolean[] nulls = null;
@Override
public long[] getLongVector()
{
computeLongs();
return longs;
}
@Nullable
@Override
public boolean[] getNullVector()
{
computeLongs();
return nulls;
}
private void computeLongs()
{
if (currentOffsetId != offset.getId()) {
currentOffsetId = offset.getId();
final Object[] values = delegate.getObjectVector();
for (int i = 0; i < values.length; i++) {
Number n = ExprEval.computeNumber(Evals.asString(values[i]));
if (n != null) {
longs[i] = n.longValue();
if (nulls != null) {
nulls[i] = false;
}
} else {
if (nulls == null) {
nulls = new boolean[offset.getMaxVectorSize()];
}
nulls[i] = true;
}
}
}
}
};
} else if (fieldSpec.expectedType != null && fieldSpec.expectedType.is(ValueType.FLOAT)) {
return new BaseFloatVectorValueSelector(offset)
{
private int currentOffsetId = ReadableVectorInspector.NULL_ID;
private final float[] floats = new float[delegate.getMaxVectorSize()];
@Nullable
private boolean[] nulls = null;
@Override
public float[] getFloatVector()
{
computeFloats();
return floats;
}
@Nullable
@Override
public boolean[] getNullVector()
{
computeFloats();
return nulls;
}
private void computeFloats()
{
if (currentOffsetId != offset.getId()) {
currentOffsetId = offset.getId();
final Object[] values = delegate.getObjectVector();
for (int i = 0; i < values.length; i++) {
Number n = ExprEval.computeNumber(Evals.asString(values[i]));
if (n != null) {
floats[i] = n.floatValue();
if (nulls != null) {
nulls[i] = false;
}
} else {
if (nulls == null) {
nulls = new boolean[offset.getMaxVectorSize()];
}
nulls[i] = true;
}
}
}
}
};
} else {
return new BaseDoubleVectorValueSelector(offset)
{
private int currentOffsetId = ReadableVectorInspector.NULL_ID;
private final double[] doubles = new double[delegate.getMaxVectorSize()];
@Nullable
private boolean[] nulls = null;
@Override
public double[] getDoubleVector()
{
computeDoubles();
return doubles;
}
@Nullable
@Override
public boolean[] getNullVector()
{
computeDoubles();
return nulls;
}
private void computeDoubles()
{
if (currentOffsetId != offset.getId()) {
currentOffsetId = offset.getId();
final Object[] values = delegate.getObjectVector();
for (int i = 0; i < values.length; i++) {
Number n = ExprEval.computeNumber(Evals.asString(values[i]));
if (n != null) {
doubles[i] = n.doubleValue();
if (nulls != null) {
nulls[i] = false;
}
} else {
if (nulls == null) {
nulls = new boolean[offset.getMaxVectorSize()];
}
nulls[i] = true;
}
}
}
}
};
}
}
return theColumn.makeVectorValueSelector(offset);
}
if (fieldSpec.parts.size() == 1 && fieldSpec.parts.get(0) instanceof NestedPathArrayElement && theColumn instanceof VariantColumn) {
final VariantColumn<?> arrayColumn = (VariantColumn<?>) theColumn;
VectorObjectSelector arraySelector = arrayColumn.makeVectorObjectSelector(offset);
final int elementNumber = ((NestedPathArrayElement) fieldSpec.parts.get(0)).getIndex();
if (elementNumber < 0) {
throw new IAE("Cannot make array element selector, negative array index not supported");
}
if (fieldSpec.expectedType != null && fieldSpec.expectedType.is(ValueType.LONG)) {
return new BaseLongVectorValueSelector(offset)
{
private final long[] longs = new long[offset.getMaxVectorSize()];
private final boolean[] nulls = new boolean[offset.getMaxVectorSize()];
private int id = ReadableVectorInspector.NULL_ID;
private void computeNumbers()
{
if (offset.getId() != id) {
final Object[] maybeArrays = arraySelector.getObjectVector();
for (int i = 0; i < arraySelector.getCurrentVectorSize(); i++) {
Object maybeArray = maybeArrays[i];
if (maybeArray instanceof Object[]) {
Object[] anArray = (Object[]) maybeArray;
if (elementNumber < anArray.length) {
if (anArray[elementNumber] instanceof Number) {
Number n = (Number) anArray[elementNumber];
longs[i] = n.longValue();
nulls[i] = false;
} else {
Double d = anArray[elementNumber] instanceof String
? Doubles.tryParse((String) anArray[elementNumber])
: null;
if (d != null) {
longs[i] = d.longValue();
nulls[i] = false;
} else {
longs[i] = 0L;
nulls[i] = true;
}
}
} else {
nullElement(i);
}
} else {
// not an array?
nullElement(i);
}
}
id = offset.getId();
}
}
private void nullElement(int i)
{
longs[i] = 0L;
nulls[i] = true;
}
@Override
public long[] getLongVector()
{
if (offset.getId() != id) {
computeNumbers();
}
return longs;
}
@Nullable
@Override
public boolean[] getNullVector()
{
if (offset.getId() != id) {
computeNumbers();
}
return nulls;
}
};
} else if (fieldSpec.expectedType != null && fieldSpec.expectedType.is(ValueType.FLOAT)) {
return new BaseFloatVectorValueSelector(offset)
{
private final float[] floats = new float[offset.getMaxVectorSize()];
private final boolean[] nulls = new boolean[offset.getMaxVectorSize()];
private int id = ReadableVectorInspector.NULL_ID;
private void computeNumbers()
{
if (offset.getId() != id) {
final Object[] maybeArrays = arraySelector.getObjectVector();
for (int i = 0; i < arraySelector.getCurrentVectorSize(); i++) {
Object maybeArray = maybeArrays[i];
if (maybeArray instanceof Object[]) {
Object[] anArray = (Object[]) maybeArray;
if (elementNumber < anArray.length) {
if (anArray[elementNumber] instanceof Number) {
Number n = (Number) anArray[elementNumber];
floats[i] = n.floatValue();
nulls[i] = false;
} else {
Double d = anArray[elementNumber] instanceof String
? Doubles.tryParse((String) anArray[elementNumber])
: null;
if (d != null) {
floats[i] = d.floatValue();
nulls[i] = false;
} else {
nullElement(i);
}
}
} else {
nullElement(i);
}
} else {
// not an array?
nullElement(i);
}
}
id = offset.getId();
}
}
private void nullElement(int i)
{
floats[i] = 0f;
nulls[i] = true;
}
@Override
public float[] getFloatVector()
{
if (offset.getId() != id) {
computeNumbers();
}
return floats;
}
@Nullable
@Override
public boolean[] getNullVector()
{
if (offset.getId() != id) {
computeNumbers();
}
return nulls;
}
};
} else {
return new BaseDoubleVectorValueSelector(offset)
{
private final double[] doubles = new double[offset.getMaxVectorSize()];
private final boolean[] nulls = new boolean[offset.getMaxVectorSize()];
private int id = ReadableVectorInspector.NULL_ID;
private void computeNumbers()
{
if (offset.getId() != id) {
final Object[] maybeArrays = arraySelector.getObjectVector();
for (int i = 0; i < arraySelector.getCurrentVectorSize(); i++) {
Object maybeArray = maybeArrays[i];
if (maybeArray instanceof Object[]) {
Object[] anArray = (Object[]) maybeArray;
if (elementNumber < anArray.length) {
if (anArray[elementNumber] instanceof Number) {
Number n = (Number) anArray[elementNumber];
doubles[i] = n.doubleValue();
nulls[i] = false;
} else {
Double d = anArray[elementNumber] instanceof String
? Doubles.tryParse((String) anArray[elementNumber])
: null;
if (d != null) {
doubles[i] = d;
nulls[i] = false;
} else {
nullElement(i);
}
}
} else {
nullElement(i);
}
} else {
// not an array?
nullElement(i);
}
}
id = offset.getId();
}
}
private void nullElement(int i)
{
doubles[i] = 0.0;
nulls[i] = true;
}
@Override
public double[] getDoubleVector()
{
if (offset.getId() != id) {
computeNumbers();
}
return doubles;
}
@Nullable
@Override
public boolean[] getNullVector()
{
if (offset.getId() != id) {
computeNumbers();
}
return nulls;
}
};
}
}
return NilVectorSelector.create(offset);
}
final NestedDataComplexColumn column = (NestedDataComplexColumn) theColumn;
// if column is numeric, it has a vector value selector, so we can directly make a vector value selector
// if we are missing an expectedType, then we've got nothing else to work with so try it anyway
if (column.isNumeric(fieldSpec.parts) || fieldSpec.expectedType == null) {
return column.makeVectorValueSelector(fieldSpec.parts, offset);
}
final VectorObjectSelector objectSelector = column.makeVectorObjectSelector(fieldSpec.parts, offset);
if (fieldSpec.expectedType.is(ValueType.LONG)) {
return new BaseLongVectorValueSelector(offset)
{
private final long[] longVector = new long[offset.getMaxVectorSize()];
@Nullable
private boolean[] nullVector = null;
private int id = ReadableVectorInspector.NULL_ID;
@Override
public long[] getLongVector()
{
computeVectorsIfNeeded();
return longVector;
}
@Nullable
@Override
public boolean[] getNullVector()
{
computeVectorsIfNeeded();
return nullVector;
}
private void computeVectorsIfNeeded()
{
if (id == offset.getId()) {
return;
}
id = offset.getId();
final Object[] vals = objectSelector.getObjectVector();
for (int i = 0; i < objectSelector.getCurrentVectorSize(); i++) {
Object v = vals[i];
if (v == null) {
if (nullVector == null) {
nullVector = new boolean[objectSelector.getMaxVectorSize()];
}
longVector[i] = 0L;
nullVector[i] = true;
} else {
Long l;
if (v instanceof Number) {
l = ((Number) v).longValue();
} else {
final String s = String.valueOf(v);
l = GuavaUtils.tryParseLong(s);
if (l == null) {
final Double d = Doubles.tryParse(s);
if (d != null) {
l = d.longValue();
}
}
}
if (l != null) {
longVector[i] = l;
if (nullVector != null) {
nullVector[i] = false;
}
} else {
if (nullVector == null) {
nullVector = new boolean[objectSelector.getMaxVectorSize()];
}
longVector[i] = 0L;
nullVector[i] = true;
}
}
}
}
};
} else {
// treat anything else as double
return new BaseDoubleVectorValueSelector(offset)
{
private final double[] doubleVector = new double[offset.getMaxVectorSize()];
@Nullable
private boolean[] nullVector = null;
private int id = ReadableVectorInspector.NULL_ID;
@Override
public double[] getDoubleVector()
{
computeVectorsIfNeeded();
return doubleVector;
}
@Nullable
@Override
public boolean[] getNullVector()
{
computeVectorsIfNeeded();
return nullVector;
}
private void computeVectorsIfNeeded()
{
if (id == offset.getId()) {
return;
}
id = offset.getId();
final Object[] vals = objectSelector.getObjectVector();
for (int i = 0; i < objectSelector.getCurrentVectorSize(); i++) {
Object v = vals[i];
if (v == null) {
if (nullVector == null) {
nullVector = new boolean[objectSelector.getMaxVectorSize()];
}
doubleVector[i] = 0.0;
nullVector[i] = true;
} else {
Double d;
if (v instanceof Number) {
d = ((Number) v).doubleValue();
} else {
d = Doubles.tryParse(String.valueOf(v));
}
if (d != null) {
doubleVector[i] = d;
if (nullVector != null) {
nullVector[i] = false;
}
} else {
if (nullVector == null) {
nullVector = new boolean[objectSelector.getMaxVectorSize()];
}
doubleVector[i] = 0.0;
nullVector[i] = true;
}
}
}
}
};
}
}