DRILL-6172: setValueCount of VariableLengthVectors throws IOB exception when called with 0 value after clearing vectors
close apache/drill#1124 Project: http://git-wip-us.apache.org/repos/asf/drill/repo Commit: http://git-wip-us.apache.org/repos/asf/drill/commit/1c14d3c3 Tree: http://git-wip-us.apache.org/repos/asf/drill/tree/1c14d3c3 Diff: http://git-wip-us.apache.org/repos/asf/drill/diff/1c14d3c3 Branch: refs/heads/master Commit: 1c14d3c3c836515b375ae7c47c4179503b1dcee0 Parents: bcd358b Author: Sorabh Hamirwasia <shamirwa...@maprtech.com> Authored: Tue Feb 20 17:14:29 2018 -0800 Committer: Aman Sinha <asi...@maprtech.com> Committed: Fri Feb 23 14:19:13 2018 -0800 ---------------------------------------------------------------------- .../exec/record/vector/TestValueVector.java | 42 ++++++++++++++++++++ .../templates/VariableLengthVectors.java | 6 ++- 2 files changed, 47 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/drill/blob/1c14d3c3/exec/java-exec/src/test/java/org/apache/drill/exec/record/vector/TestValueVector.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/record/vector/TestValueVector.java b/exec/java-exec/src/test/java/org/apache/drill/exec/record/vector/TestValueVector.java index 621d288..ba4c79c 100644 --- a/exec/java-exec/src/test/java/org/apache/drill/exec/record/vector/TestValueVector.java +++ b/exec/java-exec/src/test/java/org/apache/drill/exec/record/vector/TestValueVector.java @@ -17,6 +17,7 @@ */ package org.apache.drill.exec.record.vector; +import static junit.framework.TestCase.fail; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -48,6 +49,7 @@ import org.apache.drill.exec.memory.BufferAllocator; import org.apache.drill.exec.memory.RootAllocatorFactory; import org.apache.drill.exec.proto.UserBitShared; import org.apache.drill.exec.record.MaterializedField; +import org.apache.drill.exec.record.VectorAccessibleUtilities; import org.apache.drill.exec.vector.BaseValueVector; import org.apache.drill.exec.vector.BitVector; import org.apache.drill.exec.vector.NullableFloat4Vector; @@ -57,6 +59,7 @@ import org.apache.drill.exec.vector.RepeatedIntVector; import org.apache.drill.exec.vector.UInt4Vector; import org.apache.drill.exec.vector.ValueVector; import org.apache.drill.exec.vector.VarCharVector; +import org.apache.drill.exec.vector.VariableWidthVector; import org.apache.drill.exec.vector.complex.ListVector; import org.apache.drill.exec.vector.complex.MapVector; import org.apache.drill.exec.vector.complex.RepeatedListVector; @@ -828,4 +831,43 @@ the interface to load has changed vector.clear(); } + /** + * For VariableLengthVectors when we clear of the vector and then explicitly set the + * ValueCount of zero, then it should not fail with IndexOutOfBoundException. + * @throws Exception + */ + @Test + public void testVarLengthVector_SetCountZeroAfterClear() throws Exception { + try { + final MaterializedField field = MaterializedField.create(EMPTY_SCHEMA_PATH, VarCharHolder.TYPE); + VariableWidthVector vector = new VarCharVector(field, allocator); + vector.allocateNew(); + vector.clear(); + assertTrue(vector.getAccessor().getValueCount() == 0); + vector.getMutator().setValueCount(0); + assertTrue(vector.getAccessor().getValueCount() == 0); + } catch (Exception ex) { + fail(); + } + } + + /** For VariableLengthVectors when we try to set value count greater than value count for which memory is allocated, + * then it should fail with IndexOutOfBoundException. + * @throws Exception + */ + @Test + public void testVarLengthVector_SetOOBCount() throws Exception { + final MaterializedField field = MaterializedField.create(EMPTY_SCHEMA_PATH, VarCharHolder.TYPE); + VariableWidthVector vector = new VarCharVector(field, allocator); + try { + vector.allocateNew(10, 1); + vector.getMutator().setValueCount(4); + fail(); + } catch (Exception ex) { + assertTrue(ex instanceof IndexOutOfBoundsException); + } finally { + vector.clear(); + } + } + } http://git-wip-us.apache.org/repos/asf/drill/blob/1c14d3c3/exec/vector/src/main/codegen/templates/VariableLengthVectors.java ---------------------------------------------------------------------- diff --git a/exec/vector/src/main/codegen/templates/VariableLengthVectors.java b/exec/vector/src/main/codegen/templates/VariableLengthVectors.java index 87dbe95..3dec3f8 100644 --- a/exec/vector/src/main/codegen/templates/VariableLengthVectors.java +++ b/exec/vector/src/main/codegen/templates/VariableLengthVectors.java @@ -700,7 +700,11 @@ public final class ${minor.class}Vector extends BaseDataValueVector implements V @Override public void setValueCount(int valueCount) { final int currentByteCapacity = getByteCapacity(); - final int idx = offsetVector.getAccessor().get(valueCount); + // Check if valueCount to be set is zero and current capacity is also zero. If yes then + // we should not call get to read start index from offset vector at that value count. + final int idx = (valueCount == 0 && currentByteCapacity == 0) + ? 0 + : offsetVector.getAccessor().get(valueCount); data.writerIndex(idx); if (valueCount > 0 && currentByteCapacity > idx * 2) { incrementAllocationMonitor();