@Override
  public void evaluate(VectorizedRowBatch batch) throws HiveException {
    if (childExpressions != null) {
      super.evaluateChildren(batch);
    }

    BytesColumnVector inV = (BytesColumnVector) batch.cols[inputColumnNum[0]];
    BytesColumnVector outputColVector = (BytesColumnVector) batch.cols[outputColumnNum];

    int n = batch.size;

    if (n == 0) {
      return;
    }

    byte[][] vector = inV.vector;
    int[] sel = batch.selected;
    int[] len = inV.length;
    int[] start = inV.start;
    outputColVector.initBuffer();
    boolean[] outputIsNull = outputColVector.isNull;

    // We do not need to do a column reset since we are carefully changing the output.
    outputColVector.isRepeating = false;

    if (inV.isRepeating) {
      if (inV.noNulls || !inV.isNull[0]) {
        outputIsNull[0] = false;
        int offset = getSubstrStartOffset(vector[0], start[0], len[0], startIdx);
        if (offset != -1) {
          outputColVector.setVal(0, vector[0], offset, len[0] - (offset - start[0]));
        } else {
          outputColVector.setVal(0, EMPTY_STRING, 0, EMPTY_STRING.length);
        }
      } else {
        outputIsNull[0] = true;
        outputColVector.noNulls = false;
        outputColVector.setVal(0, EMPTY_STRING, 0, EMPTY_STRING.length);
      }
      outputColVector.isRepeating = true;
      return;
    }

    if (batch.selectedInUse) {
      if (!inV.noNulls) /* there are nulls in the inputColVector */ {

        // Carefully handle NULLs...

        for (int i = 0; i != n; ++i) {
          int selected = sel[i];
          if (!inV.isNull[selected]) {
            outputIsNull[selected] = false;
            int offset = getSubstrStartOffset(vector[selected], start[selected], len[selected],
                startIdx);
            outputColVector.isNull[selected] = false;
            if (offset != -1) {
              outputColVector.setVal(selected, vector[selected], offset,
                  len[selected] - (offset - start[selected]));
            } else {
              outputColVector.setVal(selected, EMPTY_STRING, 0, EMPTY_STRING.length);
            }
          } else {
            outputColVector.isNull[selected] = true;
            outputColVector.noNulls = false;
          }
        }
      } else {
        for (int i = 0; i != n; ++i) {
          int selected = sel[i];
          outputColVector.isNull[selected] = false;
          int offset = getSubstrStartOffset(vector[selected], start[selected], len[selected],
              startIdx);
          if (offset != -1) {
            outputColVector.setVal(selected, vector[selected], offset,
                len[selected] - (offset - start[selected]));
          } else {
            outputColVector.setVal(selected, EMPTY_STRING, 0, EMPTY_STRING.length);
          }
        }
      }
    } else {
      if (!inV.noNulls)  /* there are nulls in the inputColVector */ {

        // Carefully handle NULLs...

        for (int i = 0; i != n; ++i) {
          if (!inV.isNull[i]) {
            outputColVector.isNull[i] = false;
            int offset = getSubstrStartOffset(vector[i], start[i], len[i], startIdx);
            if (offset != -1) {
              outputColVector.setVal(i, vector[i], offset, len[i] - (offset - start[i]));
            } else {
              outputColVector.setVal(i, EMPTY_STRING, 0, EMPTY_STRING.length);
            }
          } else {
            outputColVector.isNull[i] = true;
            outputColVector.noNulls = false;
          }
        }
      } else {
        if (!outputColVector.noNulls) {

          // Assume it is almost always a performance win to fill all of isNull so we can
          // safely reset noNulls.
          Arrays.fill(outputIsNull, false);
          outputColVector.noNulls = true;
        }
        for (int i = 0; i != n; ++i) {
          int offset = getSubstrStartOffset(vector[i], start[i], len[i], startIdx);
          if (offset != -1) {
            outputColVector.setVal(i, vector[i], offset, len[i] - (offset - start[i]));
          } else {
            outputColVector.setVal(i, EMPTY_STRING, 0, EMPTY_STRING.length);
          }
        }
      }
    }
  }
Given the substring start index param it finds the starting offset of the passed in utf8
string byte array that matches the index.
@param utf8String byte array that holds the utf8 string
@param start start offset of the byte array the string starts at
@param len length of the bytes the string holds in the byte array
@param substrStart the Start index for the substring operation
ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/StringSubstrColStart.java