public ColumnValueSelector makeColumnValueSelector()

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