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

Reply via email to