@Override
  @SuppressWarnings("unchecked")
  public boolean next(NullWritable key, Object previous) throws IOException {
    if (!ensureBatch()) {
      return false;
    }

    virtualColumnHandlers.forEach(handler -> handler.handler.accept(null));

    StructType value = (StructType) previous;
    for (int i = 0; i < schema.size(); ++i) {
      if (!included[i] || i >= getStructLength(value)) continue;
      try {
        setStructCol(value, i,
            nextValue(batch.cols[i], rowInBatch, schema.get(i), getStructCol(value, i)));
      } catch (Throwable t) {
        throwIOException(i, t);
      }
    }

    for (VirtualColumnHandler handler : virtualColumnHandlers) {
      if (handler.indexInSchema < 0 || !included[handler.indexInSchema] ||
              handler.indexInSchema >= getStructLength(value)) {
        continue;
      }
      try {
        handler.handler.accept(getStructCol(value, handler.indexInSchema));
      } catch (Throwable t) {
        throwIOException(handler.indexInSchema, t);
      }
    }

    ++rowInBatch;
    return true;
  }
Wrapper class to map a virtual column to a handler defined by subclasses of {@link BatchToRowReader}.
The handler should be a set operation which sets the value of the virtual column value
in the current row.
ql/src/java/org/apache/hadoop/hive/ql/io/BatchToRowReader.java