public VectorValueSelector makeVectorValueSelector()

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;
              }
            }
          }
        }
      };
    }
  }