@Test
  public void testSubstrStart() throws HiveException {
    // Testing no nulls and no repeating
    VectorizedRowBatch batch = new VectorizedRowBatch(2);
    BytesColumnVector v = new BytesColumnVector();
    batch.cols[0] = v;
    BytesColumnVector outV = new BytesColumnVector();
    batch.cols[1] = outV;
    byte[] data1 = "abcd string".getBytes(StandardCharsets.UTF_8);
    byte[] data2 = "efgh string".getBytes(StandardCharsets.UTF_8);
    byte[] data3 = "efgh".getBytes(StandardCharsets.UTF_8);
    batch.size = 3;
    v.noNulls = true;
    v.setRef(0, data1, 0, data1.length);
    v.isNull[0] = false;
    v.setRef(1, data2, 0, data2.length);
    v.isNull[1] = false;
    v.setRef(2, data3, 0, data3.length);
    v.isNull[2] = false;

    StringSubstrColStart expr = new StringSubstrColStart(0, 6, 1);
    expr.evaluate(batch);
    BytesColumnVector outCol = (BytesColumnVector) batch.cols[1];
    Assert.assertEquals(3, batch.size);
    Assert.assertTrue(outCol.noNulls);
    Assert.assertFalse(outCol.isRepeating);
    byte[] expected = "string".getBytes(StandardCharsets.UTF_8);
    Assert.assertEquals(0,
    StringExpr.compare(
            expected, 0, expected.length, outCol.vector[0], outCol.start[0], outCol.length[0]
        )
    );

    Assert.assertEquals(0,
    StringExpr.compare(
            expected, 0, expected.length, outCol.vector[1], outCol.start[1], outCol.length[1]
        )
    );

    // This yields empty because starting idx is out of bounds.
    Assert.assertEquals(0,
    StringExpr.compare(
            emptyString, 0, emptyString.length, outCol.vector[2], outCol.start[2], outCol.length[2]
        )
    );

    outCol.noNulls = false;
    outCol.isRepeating = true;

    // Testing negative substring index.
    // Start index -6 should yield the last 6 characters of the string

    expr = new StringSubstrColStart(0, -6, 1);
    expr.evaluate(batch);
    outCol = (BytesColumnVector) batch.cols[1];
    Assert.assertEquals(3, batch.size);
    Assert.assertFalse(outCol.isRepeating);
    Assert.assertEquals(0,
    StringExpr.compare(
            expected, 0, expected.length, outCol.vector[0], outCol.start[0], outCol.length[0]
        )
    );

    Assert.assertEquals(0,
    StringExpr.compare(
            expected, 0, expected.length, outCol.vector[1], outCol.start[1], outCol.length[1]
        )
    );

    Assert.assertEquals(0,
    StringExpr.compare(
            emptyString, 0, emptyString.length, outCol.vector[2], outCol.start[2], outCol.length[2]
        )
    );

    outCol.noNulls = false;
    outCol.isRepeating = true;

    // Testing substring starting from index 1

    expr = new StringSubstrColStart(0, 1, 1);
    expr.evaluate(batch);
    Assert.assertEquals(3, batch.size);
    Assert.assertFalse(outCol.isRepeating);

    Assert.assertEquals(0,
    StringExpr.compare(
            data1, 0, data1.length, outCol.vector[0], outCol.start[0], outCol.length[0]
        )
    );

    Assert.assertEquals(0,
    StringExpr.compare(
            data2, 0, data2.length, outCol.vector[1], outCol.start[1], outCol.length[1]
        )
    );

    Assert.assertEquals(0,
    StringExpr.compare(
            data3, 0, data3.length, outCol.vector[2], outCol.start[2], outCol.length[2]
        )
    );

    outV.noNulls = false;
    outV.isRepeating = true;

    // Testing with nulls

    expr = new StringSubstrColStart(0, 6, 1);
    v.noNulls = false;
    v.isNull[0] = true;
    expr.evaluate(batch);
    Assert.assertEquals(3, batch.size);
    Assert.assertFalse(outV.noNulls);
    Assert.assertTrue(outV.isNull[0]);

    Assert.assertEquals(0,
    StringExpr.compare(
            expected, 0, expected.length, outCol.vector[1], outCol.start[1], outCol.length[1]
        )
    );

    Assert.assertEquals(0,
    StringExpr.compare(
            emptyString, 0, emptyString.length, outCol.vector[2], outCol.start[2], outCol.length[2]
        )
    );

    outCol.noNulls = false;
    outCol.isRepeating = false;

    // Testing with repeating and no nulls

    outV = new BytesColumnVector();
    v = new BytesColumnVector();
    v.isRepeating = true;
    v.noNulls = true;
    v.setRef(0, data1, 0, data1.length);
    batch = new VectorizedRowBatch(2);
    batch.cols[0] = v;
    batch.cols[1] = outV;
    expr.evaluate(batch);
    outCol = (BytesColumnVector) batch.cols[1];
    expected = "string".getBytes(StandardCharsets.UTF_8);
    Assert.assertTrue(outV.isRepeating);
    Assert.assertTrue(outV.noNulls);
    Assert.assertEquals(0,
    StringExpr.compare(
            expected, 0, expected.length, outCol.vector[0], outCol.start[0], outCol.length[0]
        )
    );

    // Testing multiByte string substring

    v = new BytesColumnVector();
    v.isRepeating = false;
    v.noNulls = true;
    v.setRef(0, multiByte, 0, 10);
    batch.cols[0] = v;
    batch.cols[1] = outV;
    outV.isRepeating = true;
    outV.noNulls = false;
    expr = new StringSubstrColStart(0, 3, 1);
    batch.size = 1;
    expr.evaluate(batch);
    outCol = (BytesColumnVector) batch.cols[1];
    Assert.assertFalse(outV.isRepeating);
    Assert.assertEquals(0,
    StringExpr.compare(
            // 3nd char starts from index 3 and total length should be 7 bytes as max is 10
            multiByte, 3, 10 - 3, outCol.vector[0], outCol.start[0], outCol.length[0]
        )
    );


    // Testing multiByte string with reference starting mid array

    v = new BytesColumnVector();
    v.isRepeating = false;
    v.noNulls = true;

    // string is 2 chars long (a 3 byte and a 4 byte char)
    v.setRef(0, multiByte, 3, 7);
    batch.cols[0] = v;
    batch.cols[1] = outV;
    outV.isRepeating = true;
    outV.noNulls = false;
    outCol = (BytesColumnVector) batch.cols[1];
    expr = new StringSubstrColStart(0, 2, 1);
    expr.evaluate(batch);
    Assert.assertFalse(outV.isRepeating);
    Assert.assertEquals(0,
    StringExpr.compare(
            // the result is the last 1 character, which occupies 4 bytes
            multiByte, 6, 4, outCol.vector[0], outCol.start[0], outCol.length[0]
        )
    );
  }
Test vectorized expression and filter evaluation for strings.
ql/src/test/org/apache/hadoop/hive/ql/exec/vector/expressions/TestVectorStringExpressions.java