You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by we...@apache.org on 2017/11/20 19:21:45 UTC

[arrow] branch master updated: ARROW-1826: [JAVA] Avoid branching in copyFrom for fixed width scalars

This is an automated email from the ASF dual-hosted git repository.

wesm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/master by this push:
     new 284e6c9  ARROW-1826: [JAVA] Avoid branching in copyFrom for fixed width scalars
284e6c9 is described below

commit 284e6c9fbf88e77809e4b7376d9439265ad0d20d
Author: siddharth <si...@dremio.com>
AuthorDate: Mon Nov 20 14:21:40 2017 -0500

    ARROW-1826: [JAVA] Avoid branching in copyFrom for fixed width scalars
    
    cc @jacques-n , @BryanCutler , @icexelloss
    
    Note: there was no performance regression or different behavior introduced as part of refactor patches.
    
    This is something I had noticed in the old code during refactoring but lost track of it. copyFrom function for fixed width scalars does a double check if the cell in the source vector is NULL or not. The old code used to do the same.
    
    There is a straightforward way to avoid double check but the new changes avoid branch all-together; since it is fine to copy garbage from source vector as long as the validity bit is copied correctly to indicate NULL or non-NULL value in the target cell.
    
    Will add unit tests.
    
    Author: siddharth <si...@dremio.com>
    
    Closes #1325 from siddharthteotia/ARROW-1826 and squashes the following commits:
    
    8fc5b3f1 [siddharth] added unit tests
    84de0cda [siddharth] ARROW-1826: [JAVA] Avoid branching in copyFrom
---
 .../apache/arrow/vector/NullableBigIntVector.java  |    8 +-
 .../org/apache/arrow/vector/NullableBitVector.java |    7 +-
 .../apache/arrow/vector/NullableDateDayVector.java |    8 +-
 .../arrow/vector/NullableDateMilliVector.java      |    8 +-
 .../apache/arrow/vector/NullableDecimalVector.java |   10 +-
 .../apache/arrow/vector/NullableFloat4Vector.java  |    8 +-
 .../apache/arrow/vector/NullableFloat8Vector.java  |    8 +-
 .../org/apache/arrow/vector/NullableIntVector.java |    8 +-
 .../arrow/vector/NullableIntervalDayVector.java    |    8 +-
 .../arrow/vector/NullableIntervalYearVector.java   |    8 +-
 .../arrow/vector/NullableSmallIntVector.java       |    8 +-
 .../arrow/vector/NullableTimeMicroVector.java      |    8 +-
 .../arrow/vector/NullableTimeMilliVector.java      |    8 +-
 .../arrow/vector/NullableTimeNanoVector.java       |    8 +-
 .../apache/arrow/vector/NullableTimeSecVector.java |    8 +-
 .../arrow/vector/NullableTimeStampVector.java      |    8 +-
 .../apache/arrow/vector/NullableTinyIntVector.java |    8 +-
 .../apache/arrow/vector/NullableUInt1Vector.java   |    8 +-
 .../apache/arrow/vector/NullableUInt2Vector.java   |    8 +-
 .../apache/arrow/vector/NullableUInt4Vector.java   |    8 +-
 .../apache/arrow/vector/NullableUInt8Vector.java   |    8 +-
 .../java/org/apache/arrow/vector/TestCopyFrom.java | 1037 ++++++++++++++++++++
 22 files changed, 1098 insertions(+), 108 deletions(-)

diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableBigIntVector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableBigIntVector.java
index eca6592..8d44c92 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableBigIntVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableBigIntVector.java
@@ -137,11 +137,9 @@ public class NullableBigIntVector extends BaseNullableFixedWidthVector {
    * @param from source vector
    */
   public void copyFrom(int fromIndex, int thisIndex, NullableBigIntVector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    final long value = from.valueBuffer.getLong(fromIndex * TYPE_WIDTH);
+    valueBuffer.setLong(thisIndex * TYPE_WIDTH, value);
   }
 
   /**
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableBitVector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableBitVector.java
index bd363f5..086331e 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableBitVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableBitVector.java
@@ -286,11 +286,8 @@ public class NullableBitVector extends BaseNullableFixedWidthVector {
    * @param from      source vector
    */
   public void copyFrom(int fromIndex, int thisIndex, NullableBitVector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    BitVectorHelper.setValidityBit(valueBuffer, thisIndex, from.getBit(fromIndex));
   }
 
   /**
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableDateDayVector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableDateDayVector.java
index c5ddc9e..bb14d1a 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableDateDayVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableDateDayVector.java
@@ -139,11 +139,9 @@ public class NullableDateDayVector extends BaseNullableFixedWidthVector {
    * @param from source vector
    */
   public void copyFrom(int fromIndex, int thisIndex, NullableDateDayVector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    final int value = from.valueBuffer.getInt(fromIndex * TYPE_WIDTH);
+    valueBuffer.setInt(thisIndex * TYPE_WIDTH, value);
   }
 
   /**
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableDateMilliVector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableDateMilliVector.java
index 7e37055..97205c3 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableDateMilliVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableDateMilliVector.java
@@ -144,11 +144,9 @@ public class NullableDateMilliVector extends BaseNullableFixedWidthVector {
    * @param from source vector
    */
   public void copyFrom(int fromIndex, int thisIndex, NullableDateMilliVector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    final long value = from.valueBuffer.getLong(fromIndex * TYPE_WIDTH);
+    valueBuffer.setLong(thisIndex * TYPE_WIDTH, value);
   }
 
   /**
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableDecimalVector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableDecimalVector.java
index dcc5510..5d2782a 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableDecimalVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableDecimalVector.java
@@ -151,13 +151,9 @@ public class NullableDecimalVector extends BaseNullableFixedWidthVector {
    * @param from source vector
    */
   public void copyFrom(int fromIndex, int thisIndex, NullableDecimalVector from) {
-    if (from.isSet(fromIndex) != 0) {
-      from.valueBuffer.getBytes(fromIndex * TYPE_WIDTH, valueBuffer,
-              thisIndex * TYPE_WIDTH, TYPE_WIDTH);
-      BitVectorHelper.setValidityBitToOne(validityBuffer, thisIndex);
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    from.valueBuffer.getBytes(fromIndex * TYPE_WIDTH, valueBuffer,
+            thisIndex * TYPE_WIDTH, TYPE_WIDTH);
   }
 
   /**
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableFloat4Vector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableFloat4Vector.java
index 834f16c..5d7128d 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableFloat4Vector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableFloat4Vector.java
@@ -138,11 +138,9 @@ public class NullableFloat4Vector extends BaseNullableFixedWidthVector {
    * @param from source vector
    */
   public void copyFrom(int fromIndex, int thisIndex, NullableFloat4Vector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    final float value = from.valueBuffer.getFloat(fromIndex * TYPE_WIDTH);
+    valueBuffer.setFloat(thisIndex * TYPE_WIDTH, value);
   }
 
   /**
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableFloat8Vector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableFloat8Vector.java
index b054d9b..7aa5461 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableFloat8Vector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableFloat8Vector.java
@@ -138,11 +138,9 @@ public class NullableFloat8Vector extends BaseNullableFixedWidthVector {
    * @param from source vector
    */
   public void copyFrom(int fromIndex, int thisIndex, NullableFloat8Vector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    final double value = from.valueBuffer.getDouble(fromIndex * TYPE_WIDTH);
+    valueBuffer.setDouble(thisIndex * TYPE_WIDTH, value);
   }
 
   /**
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableIntVector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableIntVector.java
index e5dfbce..7c6f29a 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableIntVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableIntVector.java
@@ -143,11 +143,9 @@ public class NullableIntVector extends BaseNullableFixedWidthVector {
    * @param from      source vector
    */
   public void copyFrom(int fromIndex, int thisIndex, NullableIntVector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    final int value = from.valueBuffer.getInt(fromIndex * TYPE_WIDTH);
+    valueBuffer.setInt(thisIndex * TYPE_WIDTH, value);
   }
 
   /**
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableIntervalDayVector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableIntervalDayVector.java
index 8d2fb56..862f642 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableIntervalDayVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableIntervalDayVector.java
@@ -186,13 +186,9 @@ public class NullableIntervalDayVector extends BaseNullableFixedWidthVector {
    * @param from source vector
    */
   public void copyFrom(int fromIndex, int thisIndex, NullableIntervalDayVector from) {
-    if (from.isSet(fromIndex) != 0) {
-      BitVectorHelper.setValidityBitToOne(validityBuffer, thisIndex);
-      from.valueBuffer.getBytes(fromIndex * TYPE_WIDTH, this.valueBuffer,
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    from.valueBuffer.getBytes(fromIndex * TYPE_WIDTH, this.valueBuffer,
               thisIndex * TYPE_WIDTH, TYPE_WIDTH);
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
   }
 
   /**
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableIntervalYearVector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableIntervalYearVector.java
index ac121d2..3fba5bf 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableIntervalYearVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableIntervalYearVector.java
@@ -170,11 +170,9 @@ public class NullableIntervalYearVector extends BaseNullableFixedWidthVector {
    * @param from source vector
    */
   public void copyFrom(int fromIndex, int thisIndex, NullableIntervalYearVector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    final int value = from.valueBuffer.getInt(fromIndex * TYPE_WIDTH);
+    valueBuffer.setInt(thisIndex * TYPE_WIDTH, value);
   }
 
   /**
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableSmallIntVector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableSmallIntVector.java
index 5dd1492..d5c66b1 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableSmallIntVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableSmallIntVector.java
@@ -138,11 +138,9 @@ public class NullableSmallIntVector extends BaseNullableFixedWidthVector {
    * @param from source vector
    */
   public void copyFrom(int fromIndex, int thisIndex, NullableSmallIntVector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    final short value = from.valueBuffer.getShort(fromIndex * TYPE_WIDTH);
+    valueBuffer.setShort(thisIndex * TYPE_WIDTH, value);
   }
 
   /**
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeMicroVector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeMicroVector.java
index 25da4f6..ca8e1aa 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeMicroVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeMicroVector.java
@@ -139,11 +139,9 @@ public class NullableTimeMicroVector extends BaseNullableFixedWidthVector {
    * @param from source vector
    */
   public void copyFrom(int fromIndex, int thisIndex, NullableTimeMicroVector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    final long value = from.valueBuffer.getLong(fromIndex * TYPE_WIDTH);
+    valueBuffer.setLong(thisIndex * TYPE_WIDTH, value);
   }
 
   /**
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeMilliVector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeMilliVector.java
index 7d2d5d1..a28ccfe 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeMilliVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeMilliVector.java
@@ -140,11 +140,9 @@ public class NullableTimeMilliVector extends BaseNullableFixedWidthVector {
    * @param from source vector
    */
   public void copyFrom(int fromIndex, int thisIndex, NullableTimeMilliVector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    final int value = from.valueBuffer.getInt(fromIndex * TYPE_WIDTH);
+    valueBuffer.setInt(thisIndex * TYPE_WIDTH, value);
   }
 
   /**
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeNanoVector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeNanoVector.java
index e93a63f..e6903c0 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeNanoVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeNanoVector.java
@@ -138,11 +138,9 @@ public class NullableTimeNanoVector extends BaseNullableFixedWidthVector {
    * @param from source vector
    */
   public void copyFrom(int fromIndex, int thisIndex, NullableTimeNanoVector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    final long value = from.valueBuffer.getLong(fromIndex * TYPE_WIDTH);
+    valueBuffer.setLong(thisIndex * TYPE_WIDTH, value);
   }
 
   /**
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeSecVector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeSecVector.java
index 8329fa7..85426a3 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeSecVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeSecVector.java
@@ -138,11 +138,9 @@ public class NullableTimeSecVector extends BaseNullableFixedWidthVector {
    * @param from source vector
    */
   public void copyFrom(int fromIndex, int thisIndex, NullableTimeSecVector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    final int value = from.valueBuffer.getInt(fromIndex * TYPE_WIDTH);
+    valueBuffer.setInt(thisIndex * TYPE_WIDTH, value);
   }
 
   /**
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeStampVector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeStampVector.java
index d65cb83..e1b719f 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeStampVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableTimeStampVector.java
@@ -70,11 +70,9 @@ public abstract class NullableTimeStampVector extends BaseNullableFixedWidthVect
    * @param from source vector
    */
   public void copyFrom(int fromIndex, int thisIndex, NullableTimeStampVector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    final long value = from.valueBuffer.getLong(fromIndex * TYPE_WIDTH);
+    valueBuffer.setLong(thisIndex * TYPE_WIDTH, value);
   }
 
   /**
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableTinyIntVector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableTinyIntVector.java
index 106359d..cadfe60 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableTinyIntVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableTinyIntVector.java
@@ -138,11 +138,9 @@ public class NullableTinyIntVector extends BaseNullableFixedWidthVector {
    * @param from source vector
    */
   public void copyFrom(int fromIndex, int thisIndex, NullableTinyIntVector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    final byte value = from.valueBuffer.getByte(fromIndex * TYPE_WIDTH);
+    valueBuffer.setByte(thisIndex * TYPE_WIDTH, value);
   }
 
   /**
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableUInt1Vector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableUInt1Vector.java
index 52f6c15..ebd9b56 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableUInt1Vector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableUInt1Vector.java
@@ -108,11 +108,9 @@ public class NullableUInt1Vector extends BaseNullableFixedWidthVector {
   }
 
   public void copyFrom(int fromIndex, int thisIndex, NullableUInt1Vector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    final byte value = from.valueBuffer.getByte(fromIndex * TYPE_WIDTH);
+    valueBuffer.setByte(thisIndex * TYPE_WIDTH, value);
   }
 
   public void copyFromSafe(int fromIndex, int thisIndex, NullableUInt1Vector from) {
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableUInt2Vector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableUInt2Vector.java
index 42ba6e1..bedb3f3 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableUInt2Vector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableUInt2Vector.java
@@ -109,11 +109,9 @@ public class NullableUInt2Vector extends BaseNullableFixedWidthVector {
   }
 
   public void copyFrom(int fromIndex, int thisIndex, NullableUInt2Vector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    final char value = from.valueBuffer.getChar(fromIndex * TYPE_WIDTH);
+    valueBuffer.setChar(thisIndex * TYPE_WIDTH, value);
   }
 
   public void copyFromSafe(int fromIndex, int thisIndex, NullableUInt2Vector from) {
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableUInt4Vector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableUInt4Vector.java
index 1ec2149..99b547c 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableUInt4Vector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableUInt4Vector.java
@@ -109,11 +109,9 @@ public class NullableUInt4Vector extends BaseNullableFixedWidthVector {
   }
 
   public void copyFrom(int fromIndex, int thisIndex, NullableUInt4Vector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    final int value = from.valueBuffer.getInt(fromIndex * TYPE_WIDTH);
+    valueBuffer.setInt(thisIndex * TYPE_WIDTH, value);
   }
 
   public void copyFromSafe(int fromIndex, int thisIndex, NullableUInt4Vector from) {
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/NullableUInt8Vector.java b/java/vector/src/main/java/org/apache/arrow/vector/NullableUInt8Vector.java
index 408a810..e6664a0 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/NullableUInt8Vector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/NullableUInt8Vector.java
@@ -109,11 +109,9 @@ public class NullableUInt8Vector extends BaseNullableFixedWidthVector {
   }
 
   public void copyFrom(int fromIndex, int thisIndex, NullableUInt8Vector from) {
-    if (from.isSet(fromIndex) != 0) {
-      set(thisIndex, from.get(fromIndex));
-    } else {
-      BitVectorHelper.setValidityBit(validityBuffer, thisIndex, 0);
-    }
+    BitVectorHelper.setValidityBit(validityBuffer, thisIndex, from.isSet(fromIndex));
+    final long value = from.valueBuffer.getLong(fromIndex * TYPE_WIDTH);
+    valueBuffer.setLong(thisIndex * TYPE_WIDTH, value);
   }
 
   public void copyFromSafe(int fromIndex, int thisIndex, NullableUInt8Vector from) {
diff --git a/java/vector/src/test/java/org/apache/arrow/vector/TestCopyFrom.java b/java/vector/src/test/java/org/apache/arrow/vector/TestCopyFrom.java
new file mode 100644
index 0000000..7cdfbdf
--- /dev/null
+++ b/java/vector/src/test/java/org/apache/arrow/vector/TestCopyFrom.java
@@ -0,0 +1,1037 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.arrow.vector;
+
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.memory.RootAllocator;
+import org.apache.arrow.vector.types.Types;
+import org.joda.time.Period;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.math.BigDecimal;
+
+import static org.apache.arrow.vector.TestUtils.newVector;
+import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+/**
+ * Tested field types:
+ *
+ * NullableInt
+ * NullableBigInt
+ * NullableFloat4
+ * NullableFloat8
+ * NullableBit
+ * NullableDecimal
+ * NullableIntervalDay
+ * NullableIntervalYear
+ * NullableSmallInt
+ * NullableTinyInt
+ * NullableVarChar
+ * NullableTimeMicro
+ * NullableTimeMilli
+ * NullableTimeStamp*
+ */
+
+public class TestCopyFrom {
+
+  private final static String EMPTY_SCHEMA_PATH = "";
+
+  private BufferAllocator allocator;
+
+  @Before
+  public void init() {
+    allocator = new RootAllocator(Long.MAX_VALUE);
+  }
+
+  @After
+  public void terminate() throws Exception {
+    allocator.close();
+  }
+
+  @Test /* NullableVarChar */
+  public void testCopyFromWithNulls() {
+    try (final NullableVarCharVector vector = newVector(NullableVarCharVector.class, EMPTY_SCHEMA_PATH, Types.MinorType.VARCHAR, allocator);
+         final NullableVarCharVector vector2 = newVector(NullableVarCharVector.class, EMPTY_SCHEMA_PATH, Types.MinorType.VARCHAR, allocator)) {
+
+      vector.allocateNew();
+      int capacity = vector.getValueCapacity();
+      assertEquals(4095, capacity);
+
+      for (int i = 0; i < 4095; i++) {
+        if (i % 3 == 0) {
+          continue;
+        }
+        byte[] b = Integer.toString(i).getBytes();
+        vector.setSafe(i, b, 0, b.length);
+      }
+
+      /* NO reAlloc() should have happened in setSafe() */
+      capacity = vector.getValueCapacity();
+      assertEquals(4095, capacity);
+
+      vector.setValueCount(4095);
+
+      for (int i = 0; i < 4095; i++) {
+        if (i % 3 == 0) {
+          assertNull(vector.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i, Integer.toString(i), vector.getObject(i).toString());
+        }
+      }
+
+      vector2.allocateNew();
+      capacity = vector2.getValueCapacity();
+      assertEquals(4095, capacity);
+
+      for (int i = 0; i < 4095; i++) {
+        vector2.copyFromSafe(i, i, vector);
+        if (i % 3 == 0) {
+          assertNull(vector2.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i, Integer.toString(i), vector2.getObject(i).toString());
+        }
+      }
+
+      /* NO reAlloc() should have happened in copyFrom */
+      capacity = vector2.getValueCapacity();
+      assertEquals(4095, capacity);
+
+      vector2.setValueCount(4095);
+
+      for (int i = 0; i < 4095; i++) {
+        if (i % 3 == 0) {
+          assertNull(vector2.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i, Integer.toString(i), vector2.getObject(i).toString());
+        }
+      }
+    }
+  }
+
+  @Test /* NullableVarChar */
+  public void testCopyFromWithNulls1() {
+    try (final NullableVarCharVector vector = newVector(NullableVarCharVector.class, EMPTY_SCHEMA_PATH, Types.MinorType.VARCHAR, allocator);
+         final NullableVarCharVector vector2 = newVector(NullableVarCharVector.class, EMPTY_SCHEMA_PATH, Types.MinorType.VARCHAR, allocator)) {
+
+      vector.allocateNew();
+      int capacity = vector.getValueCapacity();
+      assertEquals(4095, capacity);
+
+      for (int i = 0; i < 4095; i++) {
+        if (i % 3 == 0) {
+          continue;
+        }
+        byte[] b = Integer.toString(i).getBytes();
+        vector.setSafe(i, b, 0, b.length);
+      }
+
+      /* NO reAlloc() should have happened in setSafe() */
+      capacity = vector.getValueCapacity();
+      assertEquals(4095, capacity);
+
+      vector.setValueCount(4095);
+
+      for (int i = 0; i < 4095; i++) {
+        if (i % 3 == 0) {
+          assertNull(vector.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i, Integer.toString(i), vector.getObject(i).toString());
+        }
+      }
+
+      /* set lesser initial capacity than actually needed
+       * to trigger reallocs in copyFromSafe()
+       */
+      vector2.allocateNew(1024 * 10, 1024);
+
+      capacity = vector2.getValueCapacity();
+      assertEquals(1024, capacity);
+
+      for (int i = 0; i < 4095; i++) {
+        vector2.copyFromSafe(i, i, vector);
+        if (i % 3 == 0) {
+          assertNull(vector2.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i, Integer.toString(i), vector2.getObject(i).toString());
+        }
+      }
+
+      /* 2 reAllocs should have happened in copyFromSafe() */
+      capacity = vector2.getValueCapacity();
+      assertEquals(4096, capacity);
+
+      vector2.setValueCount(4095);
+
+      for (int i = 0; i < 4095; i++) {
+        if (i % 3 == 0) {
+          assertNull(vector2.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i, Integer.toString(i), vector2.getObject(i).toString());
+        }
+      }
+    }
+  }
+
+  @Test /* NullableIntVector */
+  public void testCopyFromWithNulls2() {
+    try (final NullableIntVector vector1 = new NullableIntVector(EMPTY_SCHEMA_PATH, allocator);
+         final NullableIntVector vector2 = new NullableIntVector(EMPTY_SCHEMA_PATH, allocator)) {
+
+      vector1.allocateNew();
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(0, vector1.getValueCount());
+
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          continue;
+        }
+        vector1.setSafe(i, 1000 + i);
+      }
+
+      vector1.setValueCount(4096);
+
+      /* No realloc should have happened in setSafe or
+       * setValueCount
+       */
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(4096, vector1.getValueCount());
+
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          assertNull(vector1.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i, 1000 + i, vector1.get(i));
+        }
+      }
+
+      /* set lesser initial capacity than actually needed
+       * to trigger reallocs in copyFromSafe()
+       */
+      vector2.allocateNew(1024);
+      assertEquals(1024, vector2.getValueCapacity());
+
+      for (int i = 0; i < 4096; i++) {
+        vector2.copyFromSafe(i, i, vector1);
+      }
+
+      /* 2 realloc should have happened in copyFromSafe() */
+      assertEquals(4096, vector2.getValueCapacity());
+      vector2.setValueCount(8192);
+      /* setValueCount() should have done another realloc */
+      assertEquals(8192, vector2.getValueCount());
+      assertEquals(8192, vector2.getValueCapacity());
+
+      /* check vector data after copy and realloc */
+      for (int i = 0; i < 8192; i++) {
+        if (((i&1) == 0) || (i >= 4096)) {
+          assertNull(vector2.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i, 1000 + i, vector2.get(i));
+        }
+      }
+    }
+  }
+
+  @Test /* NullableBigIntVector */
+  public void testCopyFromWithNulls3() {
+    try (final NullableBigIntVector vector1 = new NullableBigIntVector(EMPTY_SCHEMA_PATH, allocator);
+         final NullableBigIntVector vector2 = new NullableBigIntVector(EMPTY_SCHEMA_PATH, allocator)) {
+
+      vector1.allocateNew();
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(0, vector1.getValueCount());
+
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          continue;
+        }
+        vector1.setSafe(i, 10000000000L + (long)i);
+      }
+
+      vector1.setValueCount(4096);
+
+      /* No realloc should have happened in setSafe or
+       * setValueCount
+       */
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(4096, vector1.getValueCount());
+
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          assertNull(vector1.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i,
+                  10000000000L + (long)i, vector1.get(i));
+        }
+      }
+
+      /* set lesser initial capacity than actually needed
+       * to trigger reallocs in copyFromSafe()
+       */
+      vector2.allocateNew(1024);
+      assertEquals(1024, vector2.getValueCapacity());
+
+      for (int i = 0; i < 4096; i++) {
+        vector2.copyFromSafe(i, i, vector1);
+      }
+
+      /* 2 realloc should have happened in copyFromSafe() */
+      assertEquals(4096, vector2.getValueCapacity());
+      vector2.setValueCount(8192);
+      /* setValueCount() should have done another realloc */
+      assertEquals(8192, vector2.getValueCount());
+      assertEquals(8192, vector2.getValueCapacity());
+
+      /* check vector data after copy and realloc */
+      for (int i = 0; i < 8192; i++) {
+        if (((i&1) == 0) || (i >= 4096)) {
+          assertNull(vector2.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i,
+                  10000000000L + (long)i, vector2.get(i));
+        }
+      }
+    }
+  }
+
+  @Test /* NullableBitVector */
+  public void testCopyFromWithNulls4() {
+    try (final NullableBitVector vector1 = new NullableBitVector(EMPTY_SCHEMA_PATH, allocator);
+         final NullableBitVector vector2 = new NullableBitVector(EMPTY_SCHEMA_PATH, allocator)) {
+
+      vector1.allocateNew();
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(0, vector1.getValueCount());
+
+      int counter = 0;
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          continue;
+        }
+        if ((counter&1) == 0) {
+          vector1.setSafe(i, 1);
+        } else {
+          vector1.setSafe(i, 0);
+        }
+        counter++;
+      }
+
+      vector1.setValueCount(4096);
+
+      /* No realloc should have happened in setSafe or
+       * setValueCount
+       */
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(4096, vector1.getValueCount());
+
+      counter = 0;
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          assertNull(vector1.getObject(i));
+        } else {
+          if ((counter&1) == 0) {
+            assertTrue(vector1.getObject(i));
+          } else {
+            assertFalse(vector1.getObject(i));
+          }
+          counter++;
+        }
+      }
+
+      /* set lesser initial capacity than actually needed
+       * to trigger reallocs in copyFromSafe()
+       */
+      vector2.allocateNew(1024);
+      assertEquals(1024, vector2.getValueCapacity());
+
+      for (int i = 0; i < 4096; i++) {
+        vector2.copyFromSafe(i, i, vector1);
+      }
+
+      /* 2 realloc should have happened in copyFromSafe() */
+      assertEquals(4096, vector2.getValueCapacity());
+      vector2.setValueCount(8192);
+      /* setValueCount() should have done another realloc */
+      assertEquals(8192, vector2.getValueCount());
+      assertEquals(8192, vector2.getValueCapacity());
+
+      /* check vector data after copy and realloc */
+      counter = 0;
+      for (int i = 0; i < 8192; i++) {
+        if (((i&1) == 0) || (i >= 4096)) {
+          assertNull(vector2.getObject(i));
+        } else {
+          if ((counter&1) == 0) {
+            assertTrue(vector2.getObject(i));
+          } else {
+            assertFalse(vector2.getObject(i));
+          }
+          counter++;
+        }
+      }
+    }
+  }
+
+  @Test /* NullableFloat4Vector */
+  public void testCopyFromWithNulls5() {
+    try (final NullableFloat4Vector vector1 = new NullableFloat4Vector(EMPTY_SCHEMA_PATH, allocator);
+         final NullableFloat4Vector vector2 = new NullableFloat4Vector(EMPTY_SCHEMA_PATH, allocator)) {
+
+      vector1.allocateNew();
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(0, vector1.getValueCount());
+
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          continue;
+        }
+        vector1.setSafe(i, 100.25f + (float)i);
+      }
+
+      vector1.setValueCount(4096);
+
+      /* No realloc should have happened in setSafe or
+       * setValueCount
+       */
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(4096, vector1.getValueCount());
+
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          assertNull(vector1.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i,
+                  100.25f + (float)i, vector1.get(i), 0);
+        }
+      }
+
+      /* set lesser initial capacity than actually needed
+       * to trigger reallocs in copyFromSafe()
+       */
+      vector2.allocateNew(1024);
+      assertEquals(1024, vector2.getValueCapacity());
+
+      for (int i = 0; i < 4096; i++) {
+        vector2.copyFromSafe(i, i, vector1);
+      }
+
+      /* 2 realloc should have happened in copyFromSafe() */
+      assertEquals(4096, vector2.getValueCapacity());
+      vector2.setValueCount(8192);
+      /* setValueCount() should have done another realloc */
+      assertEquals(8192, vector2.getValueCount());
+      assertEquals(8192, vector2.getValueCapacity());
+
+      /* check vector data after copy and realloc */
+      for (int i = 0; i < 8192; i++) {
+        if (((i&1) == 0) || (i >= 4096)) {
+          assertNull(vector2.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i,
+                  100.25f + i*1.0f, vector2.get(i), 0);
+        }
+      }
+    }
+  }
+
+  @Test /* NullableFloat8Vector */
+  public void testCopyFromWithNulls6() {
+    try (final NullableFloat8Vector vector1 = new NullableFloat8Vector(EMPTY_SCHEMA_PATH, allocator);
+         final NullableFloat8Vector vector2 = new NullableFloat8Vector(EMPTY_SCHEMA_PATH, allocator)) {
+
+      vector1.allocateNew();
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(0, vector1.getValueCount());
+
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          continue;
+        }
+        vector1.setSafe(i, 123456.7865 + (double) i);
+      }
+
+      vector1.setValueCount(4096);
+
+      /* No realloc should have happened in setSafe or
+       * setValueCount
+       */
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(4096, vector1.getValueCount());
+
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          assertNull(vector1.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i,
+                  123456.7865 + (double) i, vector1.get(i), 0);
+        }
+      }
+
+      /* set lesser initial capacity than actually needed
+       * to trigger reallocs in copyFromSafe()
+       */
+      vector2.allocateNew(1024);
+      assertEquals(1024, vector2.getValueCapacity());
+
+      for (int i = 0; i < 4096; i++) {
+        vector2.copyFromSafe(i, i, vector1);
+      }
+
+      /* 2 realloc should have happened in copyFromSafe() */
+      assertEquals(4096, vector2.getValueCapacity());
+      vector2.setValueCount(8192);
+      /* setValueCount() should have done another realloc */
+      assertEquals(8192, vector2.getValueCount());
+      assertEquals(8192, vector2.getValueCapacity());
+
+      /* check vector data after copy and realloc */
+      for (int i = 0; i < 8192; i++) {
+        if (((i&1) == 0) || (i >= 4096)) {
+          assertNull(vector2.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i,
+                  123456.7865 + (double) i, vector2.get(i), 0);
+        }
+      }
+    }
+  }
+
+  @Test /* NullableIntervalDayVector */
+  public void testCopyFromWithNulls7() {
+    try (final NullableIntervalDayVector vector1 = new NullableIntervalDayVector(EMPTY_SCHEMA_PATH, allocator);
+         final NullableIntervalDayVector vector2 = new NullableIntervalDayVector(EMPTY_SCHEMA_PATH, allocator)) {
+
+      vector1.allocateNew();
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(0, vector1.getValueCount());
+
+      final int days = 10;
+      final int milliseconds = 10000;
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          continue;
+        }
+        vector1.setSafe(i, days + i, milliseconds + i);
+      }
+
+      vector1.setValueCount(4096);
+
+      /* No realloc should have happened in setSafe or
+       * setValueCount
+       */
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(4096, vector1.getValueCount());
+
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          assertNull(vector1.getObject(i));
+        } else {
+          final Period p = vector1.getObject(i);
+          assertEquals(days + i, p.getDays());
+          assertEquals(milliseconds + i, p.getMillis());
+        }
+      }
+
+      /* set lesser initial capacity than actually needed
+       * to trigger reallocs in copyFromSafe()
+       */
+      vector2.allocateNew(1024);
+      assertEquals(1024, vector2.getValueCapacity());
+
+      for (int i = 0; i < 4096; i++) {
+        vector2.copyFromSafe(i, i, vector1);
+      }
+
+      /* 2 realloc should have happened in copyFromSafe() */
+      assertEquals(4096, vector2.getValueCapacity());
+      vector2.setValueCount(8192);
+      /* setValueCount() should have done another realloc */
+      assertEquals(8192, vector2.getValueCount());
+      assertEquals(8192, vector2.getValueCapacity());
+
+      /* check vector data after copy and realloc */
+      for (int i = 0; i < 8192; i++) {
+        if (((i&1) == 0) || (i >= 4096)) {
+          assertNull(vector2.getObject(i));
+        } else {
+          final Period p = vector2.getObject(i);
+          assertEquals(days + i, p.getDays());
+          assertEquals(milliseconds + i, p.getMillis());
+        }
+      }
+    }
+  }
+
+  @Test /* NullableIntervalYearVector */
+  public void testCopyFromWithNulls8() {
+    try (final NullableIntervalYearVector vector1 = new NullableIntervalYearVector(EMPTY_SCHEMA_PATH, allocator);
+         final NullableIntervalYearVector vector2 = new NullableIntervalYearVector(EMPTY_SCHEMA_PATH, allocator)) {
+
+      vector1.allocateNew();
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(0, vector1.getValueCount());
+
+      final int interval = 30; /* 2 years 6 months */
+      final Period[]  periods = new Period[4096];
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          continue;
+        }
+        vector1.setSafe(i, interval + i);
+        final Period p = new Period();
+        final int years = (interval + i) / org.apache.arrow.vector.util.DateUtility.yearsToMonths;
+        final int months = (interval + i) % org.apache.arrow.vector.util.DateUtility.yearsToMonths;
+        periods[i] = p.plusYears(years).plusMonths(months);;
+      }
+
+      vector1.setValueCount(4096);
+
+      /* No realloc should have happened in setSafe or
+       * setValueCount
+       */
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(4096, vector1.getValueCount());
+
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          assertNull(vector1.getObject(i));
+        } else {
+          final Period p = vector1.getObject(i);
+          assertEquals(interval + i, vector1.get(i));
+          assertEquals(periods[i], p);
+        }
+      }
+
+      /* set lesser initial capacity than actually needed
+       * to trigger reallocs in copyFromSafe()
+       */
+      vector2.allocateNew(1024);
+      assertEquals(1024, vector2.getValueCapacity());
+
+      for (int i = 0; i < 4096; i++) {
+        vector2.copyFromSafe(i, i, vector1);
+      }
+
+      /* 2 realloc should have happened in copyFromSafe() */
+      assertEquals(4096, vector2.getValueCapacity());
+      vector2.setValueCount(8192);
+      /* setValueCount() should have done another realloc */
+      assertEquals(8192, vector2.getValueCount());
+      assertEquals(8192, vector2.getValueCapacity());
+
+      /* check vector data after copy and realloc */
+      for (int i = 0; i < 8192; i++) {
+        if (((i&1) == 0) || (i >= 4096)) {
+          assertNull(vector2.getObject(i));
+        } else {
+          final Period p = vector2.getObject(i);
+          assertEquals(periods[i], p);
+        }
+      }
+    }
+  }
+
+  @Test /* NullableSmallIntVector */
+  public void testCopyFromWithNulls9() {
+    try (final NullableSmallIntVector vector1 = new NullableSmallIntVector(EMPTY_SCHEMA_PATH, allocator);
+         final NullableSmallIntVector vector2 = new NullableSmallIntVector(EMPTY_SCHEMA_PATH, allocator)) {
+
+      vector1.allocateNew();
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(0, vector1.getValueCount());
+
+      final short val = 1000;
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          continue;
+        }
+        vector1.setSafe(i, val + (short)i);
+      }
+
+      vector1.setValueCount(4096);
+
+      /* No realloc should have happened in setSafe or
+       * setValueCount
+       */
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(4096, vector1.getValueCount());
+
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          assertNull(vector1.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i,
+                  val + (short)i, vector1.get(i));
+        }
+      }
+
+      /* set lesser initial capacity than actually needed
+       * to trigger reallocs in copyFromSafe()
+       */
+      vector2.allocateNew(1024);
+      assertEquals(1024, vector2.getValueCapacity());
+
+      for (int i = 0; i < 4096; i++) {
+        vector2.copyFromSafe(i, i, vector1);
+      }
+
+      /* 2 realloc should have happened in copyFromSafe() */
+      assertEquals(4096, vector2.getValueCapacity());
+      vector2.setValueCount(8192);
+      /* setValueCount() should have done another realloc */
+      assertEquals(8192, vector2.getValueCount());
+      assertEquals(8192, vector2.getValueCapacity());
+
+      /* check vector data after copy and realloc */
+      for (int i = 0; i < 8192; i++) {
+        if (((i&1) == 0) || (i >= 4096)) {
+          assertNull(vector2.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i,
+                  val + (short)i, vector2.get(i));
+        }
+      }
+    }
+  }
+
+  @Test /* NullableTimeMicroVector */
+  public void testCopyFromWithNulls10() {
+    try (final NullableTimeMicroVector vector1 = new NullableTimeMicroVector(EMPTY_SCHEMA_PATH, allocator);
+         final NullableTimeMicroVector vector2 = new NullableTimeMicroVector(EMPTY_SCHEMA_PATH, allocator)) {
+
+      vector1.allocateNew();
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(0, vector1.getValueCount());
+
+      final long val = 100485765432L;
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          continue;
+        }
+        vector1.setSafe(i, val + (long)i);
+      }
+
+      vector1.setValueCount(4096);
+
+      /* No realloc should have happened in setSafe or
+       * setValueCount
+       */
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(4096, vector1.getValueCount());
+
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          assertNull(vector1.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i,
+                  val + (long)i, vector1.get(i));
+        }
+      }
+
+      /* set lesser initial capacity than actually needed
+       * to trigger reallocs in copyFromSafe()
+       */
+      vector2.allocateNew(1024);
+      assertEquals(1024, vector2.getValueCapacity());
+
+      for (int i = 0; i < 4096; i++) {
+        vector2.copyFromSafe(i, i, vector1);
+      }
+
+      /* 2 realloc should have happened in copyFromSafe() */
+      assertEquals(4096, vector2.getValueCapacity());
+      vector2.setValueCount(8192);
+      /* setValueCount() should have done another realloc */
+      assertEquals(8192, vector2.getValueCount());
+      assertEquals(8192, vector2.getValueCapacity());
+
+      /* check vector data after copy and realloc */
+      for (int i = 0; i < 8192; i++) {
+        if (((i&1) == 0) || (i >= 4096)) {
+          assertNull(vector2.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i,
+                  val + (long) i, vector2.get(i));
+        }
+      }
+    }
+  }
+
+  @Test /* NullableTimeMilliVector */
+  public void testCopyFromWithNulls11() {
+    try (final NullableTimeMilliVector vector1 = new NullableTimeMilliVector(EMPTY_SCHEMA_PATH, allocator);
+         final NullableTimeMilliVector vector2 = new NullableTimeMilliVector(EMPTY_SCHEMA_PATH, allocator)) {
+
+      vector1.allocateNew();
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(0, vector1.getValueCount());
+
+      final int val = 1000;
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          continue;
+        }
+        vector1.setSafe(i, val + i);
+      }
+
+      vector1.setValueCount(4096);
+
+      /* No realloc should have happened in setSafe or
+       * setValueCount
+       */
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(4096, vector1.getValueCount());
+
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          assertNull(vector1.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i,
+                  val + i, vector1.get(i));
+        }
+      }
+
+      /* set lesser initial capacity than actually needed
+       * to trigger reallocs in copyFromSafe()
+       */
+      vector2.allocateNew(1024);
+      assertEquals(1024, vector2.getValueCapacity());
+
+      for (int i = 0; i < 4096; i++) {
+        vector2.copyFromSafe(i, i, vector1);
+      }
+
+      /* 2 realloc should have happened in copyFromSafe() */
+      assertEquals(4096, vector2.getValueCapacity());
+      vector2.setValueCount(8192);
+      /* setValueCount() should have done another realloc */
+      assertEquals(8192, vector2.getValueCount());
+      assertEquals(8192, vector2.getValueCapacity());
+
+      /* check vector data after copy and realloc */
+      for (int i = 0; i < 8192; i++) {
+        if (((i&1) == 0) || (i >= 4096)) {
+          assertNull(vector2.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i,
+                  val + i, vector2.get(i));
+        }
+      }
+    }
+  }
+
+  @Test /* NullableTinyIntVector */
+  public void testCopyFromWithNulls12() {
+    try (final NullableTinyIntVector vector1 = new NullableTinyIntVector(EMPTY_SCHEMA_PATH, allocator);
+         final NullableTinyIntVector vector2 = new NullableTinyIntVector(EMPTY_SCHEMA_PATH, allocator)) {
+
+      vector1.allocateNew();
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(0, vector1.getValueCount());
+
+      byte val = -128;
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          continue;
+        }
+        vector1.setSafe(i, val);
+        val++;
+      }
+
+      vector1.setValueCount(4096);
+
+      /* No realloc should have happened in setSafe or
+       * setValueCount
+       */
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(4096, vector1.getValueCount());
+
+      val = -128;
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          assertNull(vector1.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i, val, vector1.get(i));
+          val++;
+        }
+      }
+
+      /* set lesser initial capacity than actually needed
+       * to trigger reallocs in copyFromSafe()
+       */
+      vector2.allocateNew(1024);
+      assertEquals(1024, vector2.getValueCapacity());
+
+      for (int i = 0; i < 4096; i++) {
+        vector2.copyFromSafe(i, i, vector1);
+      }
+
+      /* 2 realloc should have happened in copyFromSafe() */
+      assertEquals(4096, vector2.getValueCapacity());
+      vector2.setValueCount(8192);
+      /* setValueCount() should have done another realloc */
+      assertEquals(8192, vector2.getValueCount());
+      assertEquals(8192, vector2.getValueCapacity());
+
+      /* check vector data after copy and realloc */
+      val = -128;
+      for (int i = 0; i < 8192; i++) {
+        if (((i&1) == 0) || (i >= 4096)) {
+          assertNull(vector2.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i, val, vector2.get(i));
+          val++;
+        }
+      }
+    }
+  }
+
+  @Test /* NullableDecimalVector */
+  public void testCopyFromWithNulls13() {
+    try (final NullableDecimalVector vector1 = new NullableDecimalVector(EMPTY_SCHEMA_PATH, allocator, 30, 16);
+         final NullableDecimalVector vector2 = new NullableDecimalVector(EMPTY_SCHEMA_PATH, allocator, 30, 16)) {
+
+      vector1.allocateNew();
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(0, vector1.getValueCount());
+
+      final double baseValue = 104567897654.876543654;
+      final BigDecimal[] decimals = new BigDecimal[4096];
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          continue;
+        }
+        BigDecimal decimal = new BigDecimal(baseValue + (double)i);
+        vector1.setSafe(i, decimal);
+        decimals[i] = decimal;
+      }
+
+      vector1.setValueCount(4096);
+
+      /* No realloc should have happened in setSafe or
+       * setValueCount
+       */
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(4096, vector1.getValueCount());
+
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          assertNull(vector1.getObject(i));
+        } else {
+          final BigDecimal decimal = vector1.getObject(i);
+          assertEquals(decimals[i], decimal);
+        }
+      }
+
+      /* set lesser initial capacity than actually needed
+       * to trigger reallocs in copyFromSafe()
+       */
+      vector2.allocateNew(1024);
+      assertEquals(1024, vector2.getValueCapacity());
+
+      for (int i = 0; i < 4096; i++) {
+        vector2.copyFromSafe(i, i, vector1);
+      }
+
+      /* 2 realloc should have happened in copyFromSafe() */
+      assertEquals(4096, vector2.getValueCapacity());
+      vector2.setValueCount(8192);
+      /* setValueCount() should have done another realloc */
+      assertEquals(8192, vector2.getValueCount());
+      assertEquals(8192, vector2.getValueCapacity());
+
+      /* check vector data after copy and realloc */
+      for (int i = 0; i < 8192; i++) {
+        if (((i&1) == 0) || (i >= 4096)) {
+          assertNull(vector2.getObject(i));
+        } else {
+          final BigDecimal decimal = vector2.getObject(i);
+          assertEquals(decimals[i], decimal);
+        }
+      }
+    }
+  }
+
+  @Test /* NullableTimeStampVector */
+  public void testCopyFromWithNulls14() {
+    try (final NullableTimeStampVector vector1 = new NullableTimeStampMicroVector(EMPTY_SCHEMA_PATH, allocator);
+         final NullableTimeStampVector vector2 = new NullableTimeStampMicroVector(EMPTY_SCHEMA_PATH, allocator)) {
+
+      vector1.allocateNew();
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(0, vector1.getValueCount());
+
+      final long val = 20145678912L;
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          continue;
+        }
+        vector1.setSafe(i, val + (long)i);
+      }
+
+      vector1.setValueCount(4096);
+
+      /* No realloc should have happened in setSafe or
+       * setValueCount
+       */
+      assertEquals(4096, vector1.getValueCapacity());
+      assertEquals(4096, vector1.getValueCount());
+
+      for (int i = 0; i < 4096; i++) {
+        if ((i&1) == 0) {
+          assertNull(vector1.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i,
+                  val + (long)i, vector1.get(i));
+        }
+      }
+
+      /* set lesser initial capacity than actually needed
+       * to trigger reallocs in copyFromSafe()
+       */
+      vector2.allocateNew(1024);
+      assertEquals(1024, vector2.getValueCapacity());
+
+      for (int i = 0; i < 4096; i++) {
+        vector2.copyFromSafe(i, i, vector1);
+      }
+
+      /* 2 realloc should have happened in copyFromSafe() */
+      assertEquals(4096, vector2.getValueCapacity());
+      vector2.setValueCount(8192);
+      /* setValueCount() should have done another realloc */
+      assertEquals(8192, vector2.getValueCount());
+      assertEquals(8192, vector2.getValueCapacity());
+
+      /* check vector data after copy and realloc */
+      for (int i = 0; i < 8192; i++) {
+        if (((i&1) == 0) || (i >= 4096)) {
+          assertNull(vector2.getObject(i));
+        } else {
+          assertEquals("unexpected value at index: " + i,
+                  val + (long) i, vector2.get(i));
+        }
+      }
+    }
+  }
+}

-- 
To stop receiving notification emails like this one, please contact
['"commits@arrow.apache.org" <co...@arrow.apache.org>'].