Add copy slice methods to all Column classes

diff --git a/java/common/src/main/java/org/apache/tsfile/block/column/Column.java b/java/common/src/main/java/org/apache/tsfile/block/column/Column.java
index 6db30a2..161a2c8 100644
--- a/java/common/src/main/java/org/apache/tsfile/block/column/Column.java
+++ b/java/common/src/main/java/org/apache/tsfile/block/column/Column.java
@@ -143,11 +143,23 @@
   Column getRegion(int positionOffset, int length);
 
   /**
+   * Returns a column starting at the specified position and extends for the specified length. The
+   * specified region must be entirely contained within this column.
+   *
+   * <p>The region is a copy over this column. If this column is released, the region column won't
+   * be affected.
+   */
+  Column getRegionCopy(int positionOffset, int length);
+
+  /**
    * This method will create a temporary view of origin column, which will reuse the array of column
    * but with different array offset.
    */
   Column subColumn(int fromIndex);
 
+  /** This method will create a copy of origin column with different array offset. */
+  Column subColumnCopy(int fromIndex);
+
   /** reverse the column */
   void reverse();
 
diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/BinaryColumn.java b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/BinaryColumn.java
index facd747..beb48c2 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/BinaryColumn.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/BinaryColumn.java
@@ -141,6 +141,19 @@
   }
 
   @Override
+  public Column getRegionCopy(int positionOffset, int length) {
+    checkValidRegion(getPositionCount(), positionOffset, length);
+
+    int from = positionOffset + arrayOffset;
+    int to = from + length;
+    boolean[] valueIsNullCopy =
+        valueIsNull != null ? Arrays.copyOfRange(valueIsNull, from, to) : null;
+    Binary[] valuesCopy = Arrays.copyOfRange(values, from, to);
+
+    return new BinaryColumn(0, length, valueIsNullCopy, valuesCopy);
+  }
+
+  @Override
   public Column subColumn(int fromIndex) {
     if (fromIndex > positionCount) {
       throw new IllegalArgumentException("fromIndex is not valid");
@@ -150,6 +163,21 @@
   }
 
   @Override
+  public Column subColumnCopy(int fromIndex) {
+    if (fromIndex > positionCount) {
+      throw new IllegalArgumentException("fromIndex is not valid");
+    }
+
+    int from = arrayOffset + fromIndex;
+    boolean[] valueIsNullCopy =
+        valueIsNull != null ? Arrays.copyOfRange(valueIsNull, from, positionCount) : null;
+    Binary[] valuesCopy = Arrays.copyOfRange(values, from, positionCount);
+
+    int length = positionCount - fromIndex;
+    return new BinaryColumn(0, length, valueIsNullCopy, valuesCopy);
+  }
+
+  @Override
   public void reverse() {
     for (int i = arrayOffset, j = arrayOffset + positionCount - 1; i < j; i++, j--) {
       Binary valueTmp = values[i];
diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/BooleanColumn.java b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/BooleanColumn.java
index d7d7df6..f74bcd8 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/BooleanColumn.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/BooleanColumn.java
@@ -139,6 +139,19 @@
   }
 
   @Override
+  public Column getRegionCopy(int positionOffset, int length) {
+    checkValidRegion(getPositionCount(), positionOffset, length);
+
+    int from = positionOffset + arrayOffset;
+    int to = from + length;
+    boolean[] valueIsNullCopy =
+        valueIsNull != null ? Arrays.copyOfRange(valueIsNull, from, to) : null;
+    boolean[] valuesCopy = Arrays.copyOfRange(values, from, to);
+
+    return new BooleanColumn(0, length, valueIsNullCopy, valuesCopy);
+  }
+
+  @Override
   public Column subColumn(int fromIndex) {
     if (fromIndex > positionCount) {
       throw new IllegalArgumentException("fromIndex is not valid");
@@ -148,6 +161,21 @@
   }
 
   @Override
+  public Column subColumnCopy(int fromIndex) {
+    if (fromIndex > positionCount) {
+      throw new IllegalArgumentException("fromIndex is not valid");
+    }
+
+    int from = arrayOffset + fromIndex;
+    boolean[] valueIsNullCopy =
+        valueIsNull != null ? Arrays.copyOfRange(valueIsNull, from, positionCount) : null;
+    boolean[] valuesCopy = Arrays.copyOfRange(values, from, positionCount);
+
+    int length = positionCount - fromIndex;
+    return new BooleanColumn(0, length, valueIsNullCopy, valuesCopy);
+  }
+
+  @Override
   public void reverse() {
     for (int i = arrayOffset, j = arrayOffset + positionCount - 1; i < j; i++, j--) {
       boolean valueTmp = values[i];
diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/DoubleColumn.java b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/DoubleColumn.java
index 5047028..0311830 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/DoubleColumn.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/DoubleColumn.java
@@ -140,6 +140,19 @@
   }
 
   @Override
+  public Column getRegionCopy(int positionOffset, int length) {
+    checkValidRegion(getPositionCount(), positionOffset, length);
+
+    int from = positionOffset + arrayOffset;
+    int to = from + length;
+    boolean[] valueIsNullCopy =
+        valueIsNull != null ? Arrays.copyOfRange(valueIsNull, from, to) : null;
+    double[] valuesCopy = Arrays.copyOfRange(values, from, to);
+
+    return new DoubleColumn(0, length, valueIsNullCopy, valuesCopy);
+  }
+
+  @Override
   public Column subColumn(int fromIndex) {
     if (fromIndex > positionCount) {
       throw new IllegalArgumentException("fromIndex is not valid");
@@ -149,6 +162,21 @@
   }
 
   @Override
+  public Column subColumnCopy(int fromIndex) {
+    if (fromIndex > positionCount) {
+      throw new IllegalArgumentException("fromIndex is not valid");
+    }
+
+    int from = arrayOffset + fromIndex;
+    boolean[] valueIsNullCopy =
+        valueIsNull != null ? Arrays.copyOfRange(valueIsNull, from, positionCount) : null;
+    double[] valuesCopy = Arrays.copyOfRange(values, from, positionCount);
+
+    int length = positionCount - fromIndex;
+    return new DoubleColumn(0, length, valueIsNullCopy, valuesCopy);
+  }
+
+  @Override
   public void reverse() {
     for (int i = arrayOffset, j = arrayOffset + positionCount - 1; i < j; i++, j--) {
       double valueTmp = values[i];
diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/FloatColumn.java b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/FloatColumn.java
index 4050ad1..449212e 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/FloatColumn.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/FloatColumn.java
@@ -140,6 +140,19 @@
   }
 
   @Override
+  public Column getRegionCopy(int positionOffset, int length) {
+    checkValidRegion(getPositionCount(), positionOffset, length);
+
+    int from = positionOffset + arrayOffset;
+    int to = from + length;
+    boolean[] valueIsNullCopy =
+        valueIsNull != null ? Arrays.copyOfRange(valueIsNull, from, to) : null;
+    float[] valuesCopy = Arrays.copyOfRange(values, from, to);
+
+    return new FloatColumn(0, length, valueIsNullCopy, valuesCopy);
+  }
+
+  @Override
   public Column subColumn(int fromIndex) {
     if (fromIndex > positionCount) {
       throw new IllegalArgumentException("fromIndex is not valid");
@@ -148,6 +161,21 @@
   }
 
   @Override
+  public Column subColumnCopy(int fromIndex) {
+    if (fromIndex > positionCount) {
+      throw new IllegalArgumentException("fromIndex is not valid");
+    }
+
+    int from = arrayOffset + fromIndex;
+    boolean[] valueIsNullCopy =
+        valueIsNull != null ? Arrays.copyOfRange(valueIsNull, from, positionCount) : null;
+    float[] valuesCopy = Arrays.copyOfRange(values, from, positionCount);
+
+    int length = positionCount - fromIndex;
+    return new FloatColumn(0, length, valueIsNullCopy, valuesCopy);
+  }
+
+  @Override
   public void reverse() {
     for (int i = arrayOffset, j = arrayOffset + positionCount - 1; i < j; i++, j--) {
       float valueTmp = values[i];
diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/IntColumn.java b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/IntColumn.java
index 8355f28..0254690 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/IntColumn.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/IntColumn.java
@@ -140,6 +140,19 @@
   }
 
   @Override
+  public Column getRegionCopy(int positionOffset, int length) {
+    checkValidRegion(getPositionCount(), positionOffset, length);
+
+    int from = positionOffset + arrayOffset;
+    int to = from + length;
+    boolean[] valueIsNullCopy =
+        valueIsNull != null ? Arrays.copyOfRange(valueIsNull, from, to) : null;
+    int[] valuesCopy = Arrays.copyOfRange(values, from, to);
+
+    return new IntColumn(0, length, valueIsNullCopy, valuesCopy);
+  }
+
+  @Override
   public Column subColumn(int fromIndex) {
     if (fromIndex > positionCount) {
       throw new IllegalArgumentException("fromIndex is not valid");
@@ -148,6 +161,21 @@
   }
 
   @Override
+  public Column subColumnCopy(int fromIndex) {
+    if (fromIndex > positionCount) {
+      throw new IllegalArgumentException("fromIndex is not valid");
+    }
+
+    int from = arrayOffset + fromIndex;
+    boolean[] valueIsNullCopy =
+        valueIsNull != null ? Arrays.copyOfRange(valueIsNull, from, positionCount) : null;
+    int[] valuesCopy = Arrays.copyOfRange(values, from, positionCount);
+
+    int length = positionCount - fromIndex;
+    return new IntColumn(0, length, valueIsNullCopy, valuesCopy);
+  }
+
+  @Override
   public void reverse() {
     for (int i = arrayOffset, j = arrayOffset + positionCount - 1; i < j; i++, j--) {
       int valueTmp = values[i];
diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/LongColumn.java b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/LongColumn.java
index 59b8e01..34cc7dc 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/LongColumn.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/LongColumn.java
@@ -140,6 +140,19 @@
   }
 
   @Override
+  public Column getRegionCopy(int positionOffset, int length) {
+    checkValidRegion(getPositionCount(), positionOffset, length);
+
+    int from = positionOffset + arrayOffset;
+    int to = from + length;
+    boolean[] valueIsNullCopy =
+        valueIsNull != null ? Arrays.copyOfRange(valueIsNull, from, to) : null;
+    long[] valuesCopy = Arrays.copyOfRange(values, from, to);
+
+    return new LongColumn(0, length, valueIsNullCopy, valuesCopy);
+  }
+
+  @Override
   public Column subColumn(int fromIndex) {
     if (fromIndex > positionCount) {
       throw new IllegalArgumentException("fromIndex is not valid");
@@ -148,6 +161,21 @@
   }
 
   @Override
+  public Column subColumnCopy(int fromIndex) {
+    if (fromIndex > positionCount) {
+      throw new IllegalArgumentException("fromIndex is not valid");
+    }
+
+    int from = arrayOffset + fromIndex;
+    boolean[] valueIsNullCopy =
+        valueIsNull != null ? Arrays.copyOfRange(valueIsNull, from, positionCount) : null;
+    long[] valuesCopy = Arrays.copyOfRange(values, from, positionCount);
+
+    int length = positionCount - fromIndex;
+    return new LongColumn(0, length, valueIsNullCopy, valuesCopy);
+  }
+
+  @Override
   public void reverse() {
     for (int i = arrayOffset, j = arrayOffset + positionCount - 1; i < j; i++, j--) {
       long valueTmp = values[i];
diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/NullColumn.java b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/NullColumn.java
index f95cdb0..8b7e215 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/NullColumn.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/NullColumn.java
@@ -90,6 +90,11 @@
   }
 
   @Override
+  public Column getRegionCopy(int positionOffset, int length) {
+    return getRegion(positionOffset, length);
+  }
+
+  @Override
   public Column subColumn(int fromIndex) {
     if (fromIndex > positionCount) {
       throw new IllegalArgumentException("fromIndex is not valid");
@@ -98,6 +103,11 @@
   }
 
   @Override
+  public Column subColumnCopy(int fromIndex) {
+    return subColumn(fromIndex);
+  }
+
+  @Override
   public void reverse() {
     // do nothing
   }
diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/RunLengthEncodedColumn.java b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/RunLengthEncodedColumn.java
index dbca629..a78e2da 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/RunLengthEncodedColumn.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/RunLengthEncodedColumn.java
@@ -198,6 +198,13 @@
   }
 
   @Override
+  public Column getRegionCopy(int positionOffset, int length) {
+    checkValidRegion(positionCount, positionOffset, length);
+    Column valueCopy = value.subColumnCopy(0);
+    return new RunLengthEncodedColumn(valueCopy, length);
+  }
+
+  @Override
   public Column subColumn(int fromIndex) {
     if (fromIndex > positionCount) {
       throw new IllegalArgumentException("fromIndex is not valid");
@@ -206,6 +213,15 @@
   }
 
   @Override
+  public Column subColumnCopy(int fromIndex) {
+    if (fromIndex > positionCount) {
+      throw new IllegalArgumentException("fromIndex is not valid");
+    }
+    Column valueCopy = value.subColumnCopy(0);
+    return new RunLengthEncodedColumn(valueCopy, positionCount - fromIndex);
+  }
+
+  @Override
   public void reverse() {
     // do nothing because the underlying column has only one value
   }
diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/TimeColumn.java b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/TimeColumn.java
index aa629d5..1783f6a 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/TimeColumn.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/TimeColumn.java
@@ -24,6 +24,8 @@
 import org.apache.tsfile.enums.TSDataType;
 import org.apache.tsfile.utils.RamUsageEstimator;
 
+import java.util.Arrays;
+
 import static org.apache.tsfile.utils.RamUsageEstimator.sizeOfLongArray;
 
 public class TimeColumn implements Column {
@@ -117,6 +119,17 @@
   }
 
   @Override
+  public Column getRegionCopy(int positionOffset, int length) {
+    ColumnUtil.checkValidRegion(getPositionCount(), positionOffset, length);
+
+    int from = positionOffset + arrayOffset;
+    int to = from + length;
+    long[] valuesCopy = Arrays.copyOfRange(values, from, to);
+
+    return new TimeColumn(0, length, valuesCopy);
+  }
+
+  @Override
   public Column subColumn(int fromIndex) {
     if (fromIndex > positionCount) {
       throw new IllegalArgumentException("fromIndex is not valid");
@@ -125,6 +138,19 @@
   }
 
   @Override
+  public Column subColumnCopy(int fromIndex) {
+    if (fromIndex > positionCount) {
+      throw new IllegalArgumentException("fromIndex is not valid");
+    }
+
+    int from = arrayOffset + fromIndex;
+    long[] valuesCopy = Arrays.copyOfRange(values, from, positionCount);
+
+    int length = positionCount - fromIndex;
+    return new TimeColumn(0, length, valuesCopy);
+  }
+
+  @Override
   public void reverse() {
     for (int i = arrayOffset, j = arrayOffset + positionCount - 1; i < j; i++, j--) {
       long time = values[i];
diff --git a/java/tsfile/src/test/java/org/apache/tsfile/read/common/ColumnTest.java b/java/tsfile/src/test/java/org/apache/tsfile/read/common/ColumnTest.java
index d7b6155..80ac448 100644
--- a/java/tsfile/src/test/java/org/apache/tsfile/read/common/ColumnTest.java
+++ b/java/tsfile/src/test/java/org/apache/tsfile/read/common/ColumnTest.java
@@ -49,16 +49,38 @@
     for (int i = 0; i < 10; i++) {
       columnBuilder.writeLong(i);
     }
-    TimeColumn timeColumn = (TimeColumn) columnBuilder.build();
-    timeColumn = (TimeColumn) timeColumn.subColumn(5);
-    Assert.assertEquals(5, timeColumn.getPositionCount());
-    Assert.assertEquals(5, timeColumn.getLong(0));
-    Assert.assertEquals(9, timeColumn.getLong(4));
+    TimeColumn timeColumn1 = (TimeColumn) columnBuilder.build();
+    timeColumn1 = (TimeColumn) timeColumn1.subColumn(5);
+    Assert.assertEquals(5, timeColumn1.getPositionCount());
+    Assert.assertEquals(5, timeColumn1.getLong(0));
+    Assert.assertEquals(9, timeColumn1.getLong(4));
 
-    timeColumn = (TimeColumn) timeColumn.subColumn(3);
-    Assert.assertEquals(2, timeColumn.getPositionCount());
-    Assert.assertEquals(8, timeColumn.getLong(0));
-    Assert.assertEquals(9, timeColumn.getLong(1));
+    TimeColumn timeColumn2 = (TimeColumn) timeColumn1.subColumn(3);
+    Assert.assertEquals(2, timeColumn2.getPositionCount());
+    Assert.assertEquals(8, timeColumn2.getLong(0));
+    Assert.assertEquals(9, timeColumn2.getLong(1));
+
+    Assert.assertSame(timeColumn1.getLongs(), timeColumn2.getLongs());
+  }
+
+  @Test
+  public void timeColumnSubColumnCopyTest() {
+    TimeColumnBuilder columnBuilder = new TimeColumnBuilder(null, 10);
+    for (int i = 0; i < 10; i++) {
+      columnBuilder.writeLong(i);
+    }
+    TimeColumn timeColumn1 = (TimeColumn) columnBuilder.build();
+    timeColumn1 = (TimeColumn) timeColumn1.subColumnCopy(5);
+    Assert.assertEquals(5, timeColumn1.getPositionCount());
+    Assert.assertEquals(5, timeColumn1.getLong(0));
+    Assert.assertEquals(9, timeColumn1.getLong(4));
+
+    TimeColumn timeColumn2 = (TimeColumn) timeColumn1.subColumnCopy(3);
+    Assert.assertEquals(2, timeColumn2.getPositionCount());
+    Assert.assertEquals(8, timeColumn2.getLong(0));
+    Assert.assertEquals(9, timeColumn2.getLong(1));
+
+    Assert.assertNotSame(timeColumn1.getLongs(), timeColumn2.getLongs());
   }
 
   @Test
@@ -67,16 +89,38 @@
     for (int i = 0; i < 10; i++) {
       columnBuilder.writeBinary(BytesUtils.valueOf(String.valueOf(i)));
     }
-    BinaryColumn binaryColumn = (BinaryColumn) columnBuilder.build();
-    binaryColumn = (BinaryColumn) binaryColumn.subColumn(5);
-    Assert.assertEquals(5, binaryColumn.getPositionCount());
-    Assert.assertEquals("5", binaryColumn.getBinary(0).toString());
-    Assert.assertEquals("9", binaryColumn.getBinary(4).toString());
+    BinaryColumn binaryColumn1 = (BinaryColumn) columnBuilder.build();
+    binaryColumn1 = (BinaryColumn) binaryColumn1.subColumn(5);
+    Assert.assertEquals(5, binaryColumn1.getPositionCount());
+    Assert.assertEquals("5", binaryColumn1.getBinary(0).toString());
+    Assert.assertEquals("9", binaryColumn1.getBinary(4).toString());
 
-    binaryColumn = (BinaryColumn) binaryColumn.subColumn(3);
-    Assert.assertEquals(2, binaryColumn.getPositionCount());
-    Assert.assertEquals("8", binaryColumn.getBinary(0).toString());
-    Assert.assertEquals("9", binaryColumn.getBinary(1).toString());
+    BinaryColumn binaryColumn2 = (BinaryColumn) binaryColumn1.subColumn(3);
+    Assert.assertEquals(2, binaryColumn2.getPositionCount());
+    Assert.assertEquals("8", binaryColumn2.getBinary(0).toString());
+    Assert.assertEquals("9", binaryColumn2.getBinary(1).toString());
+
+    Assert.assertSame(binaryColumn1.getBinaries(), binaryColumn2.getBinaries());
+  }
+
+  @Test
+  public void binaryColumnSubColumnCopyTest() {
+    BinaryColumnBuilder columnBuilder = new BinaryColumnBuilder(null, 10);
+    for (int i = 0; i < 10; i++) {
+      columnBuilder.writeBinary(BytesUtils.valueOf(String.valueOf(i)));
+    }
+    BinaryColumn binaryColumn1 = (BinaryColumn) columnBuilder.build();
+    binaryColumn1 = (BinaryColumn) binaryColumn1.subColumnCopy(5);
+    Assert.assertEquals(5, binaryColumn1.getPositionCount());
+    Assert.assertEquals("5", binaryColumn1.getBinary(0).toString());
+    Assert.assertEquals("9", binaryColumn1.getBinary(4).toString());
+
+    BinaryColumn binaryColumn2 = (BinaryColumn) binaryColumn1.subColumnCopy(3);
+    Assert.assertEquals(2, binaryColumn2.getPositionCount());
+    Assert.assertEquals("8", binaryColumn2.getBinary(0).toString());
+    Assert.assertEquals("9", binaryColumn2.getBinary(1).toString());
+
+    Assert.assertNotSame(binaryColumn1.getBinaries(), binaryColumn2.getBinaries());
   }
 
   @Test
@@ -86,16 +130,39 @@
     for (int i = 0; i < 10; i++) {
       columnBuilder.writeBoolean(i % 2 == 0);
     }
-    BooleanColumn booleanColumn = (BooleanColumn) columnBuilder.build();
-    booleanColumn = (BooleanColumn) booleanColumn.subColumn(5);
-    Assert.assertEquals(5, booleanColumn.getPositionCount());
-    Assert.assertFalse(booleanColumn.getBoolean(0));
-    Assert.assertFalse(booleanColumn.getBoolean(4));
+    BooleanColumn booleanColumn1 = (BooleanColumn) columnBuilder.build();
+    booleanColumn1 = (BooleanColumn) booleanColumn1.subColumn(5);
+    Assert.assertEquals(5, booleanColumn1.getPositionCount());
+    Assert.assertFalse(booleanColumn1.getBoolean(0));
+    Assert.assertFalse(booleanColumn1.getBoolean(4));
 
-    booleanColumn = (BooleanColumn) booleanColumn.subColumn(3);
-    Assert.assertEquals(2, booleanColumn.getPositionCount());
-    Assert.assertTrue(booleanColumn.getBoolean(0));
-    Assert.assertFalse(booleanColumn.getBoolean(1));
+    BooleanColumn booleanColumn2 = (BooleanColumn) booleanColumn1.subColumn(3);
+    Assert.assertEquals(2, booleanColumn2.getPositionCount());
+    Assert.assertTrue(booleanColumn2.getBoolean(0));
+    Assert.assertFalse(booleanColumn2.getBoolean(1));
+
+    Assert.assertSame(booleanColumn1.getBooleans(), booleanColumn2.getBooleans());
+  }
+
+  @Test
+  public void booleanColumnSubColumnCopyTest() {
+    BooleanColumnBuilder columnBuilder = new BooleanColumnBuilder(null, 10);
+    // 0: true, 1: false
+    for (int i = 0; i < 10; i++) {
+      columnBuilder.writeBoolean(i % 2 == 0);
+    }
+    BooleanColumn booleanColumn1 = (BooleanColumn) columnBuilder.build();
+    booleanColumn1 = (BooleanColumn) booleanColumn1.subColumnCopy(5);
+    Assert.assertEquals(5, booleanColumn1.getPositionCount());
+    Assert.assertFalse(booleanColumn1.getBoolean(0));
+    Assert.assertFalse(booleanColumn1.getBoolean(4));
+
+    BooleanColumn booleanColumn2 = (BooleanColumn) booleanColumn1.subColumnCopy(3);
+    Assert.assertEquals(2, booleanColumn2.getPositionCount());
+    Assert.assertTrue(booleanColumn2.getBoolean(0));
+    Assert.assertFalse(booleanColumn2.getBoolean(1));
+
+    Assert.assertNotSame(booleanColumn1.getBooleans(), booleanColumn2.getBooleans());
   }
 
   @Test
@@ -104,16 +171,38 @@
     for (int i = 0; i < 10; i++) {
       columnBuilder.writeDouble(i);
     }
-    DoubleColumn doubleColumn = (DoubleColumn) columnBuilder.build();
-    doubleColumn = (DoubleColumn) doubleColumn.subColumn(5);
-    Assert.assertEquals(5, doubleColumn.getPositionCount());
-    Assert.assertEquals(5.0, doubleColumn.getDouble(0), 0.001);
-    Assert.assertEquals(9.0, doubleColumn.getDouble(4), 0.001);
+    DoubleColumn doubleColumn1 = (DoubleColumn) columnBuilder.build();
+    doubleColumn1 = (DoubleColumn) doubleColumn1.subColumn(5);
+    Assert.assertEquals(5, doubleColumn1.getPositionCount());
+    Assert.assertEquals(5.0, doubleColumn1.getDouble(0), 0.001);
+    Assert.assertEquals(9.0, doubleColumn1.getDouble(4), 0.001);
 
-    doubleColumn = (DoubleColumn) doubleColumn.subColumn(3);
-    Assert.assertEquals(2, doubleColumn.getPositionCount());
-    Assert.assertEquals(8.0, doubleColumn.getDouble(0), 0.001);
-    Assert.assertEquals(9.0, doubleColumn.getDouble(1), 0.001);
+    DoubleColumn doubleColumn2 = (DoubleColumn) doubleColumn1.subColumn(3);
+    Assert.assertEquals(2, doubleColumn2.getPositionCount());
+    Assert.assertEquals(8.0, doubleColumn2.getDouble(0), 0.001);
+    Assert.assertEquals(9.0, doubleColumn2.getDouble(1), 0.001);
+
+    Assert.assertSame(doubleColumn1.getDoubles(), doubleColumn2.getDoubles());
+  }
+
+  @Test
+  public void doubleColumnSubColumnCopyTest() {
+    DoubleColumnBuilder columnBuilder = new DoubleColumnBuilder(null, 10);
+    for (int i = 0; i < 10; i++) {
+      columnBuilder.writeDouble(i);
+    }
+    DoubleColumn doubleColumn1 = (DoubleColumn) columnBuilder.build();
+    doubleColumn1 = (DoubleColumn) doubleColumn1.subColumnCopy(5);
+    Assert.assertEquals(5, doubleColumn1.getPositionCount());
+    Assert.assertEquals(5.0, doubleColumn1.getDouble(0), 0.001);
+    Assert.assertEquals(9.0, doubleColumn1.getDouble(4), 0.001);
+
+    DoubleColumn doubleColumn2 = (DoubleColumn) doubleColumn1.subColumnCopy(3);
+    Assert.assertEquals(2, doubleColumn2.getPositionCount());
+    Assert.assertEquals(8.0, doubleColumn2.getDouble(0), 0.001);
+    Assert.assertEquals(9.0, doubleColumn2.getDouble(1), 0.001);
+
+    Assert.assertNotSame(doubleColumn1.getDoubles(), doubleColumn2.getDoubles());
   }
 
   @Test
@@ -122,16 +211,38 @@
     for (int i = 0; i < 10; i++) {
       columnBuilder.writeFloat(i);
     }
-    FloatColumn floatColumn = (FloatColumn) columnBuilder.build();
-    floatColumn = (FloatColumn) floatColumn.subColumn(5);
-    Assert.assertEquals(5, floatColumn.getPositionCount());
-    Assert.assertEquals(5.0, floatColumn.getFloat(0), 0.001);
-    Assert.assertEquals(9.0, floatColumn.getFloat(4), 0.001);
+    FloatColumn floatColumn1 = (FloatColumn) columnBuilder.build();
+    floatColumn1 = (FloatColumn) floatColumn1.subColumn(5);
+    Assert.assertEquals(5, floatColumn1.getPositionCount());
+    Assert.assertEquals(5.0, floatColumn1.getFloat(0), 0.001);
+    Assert.assertEquals(9.0, floatColumn1.getFloat(4), 0.001);
 
-    floatColumn = (FloatColumn) floatColumn.subColumn(3);
-    Assert.assertEquals(2, floatColumn.getPositionCount());
-    Assert.assertEquals(8.0, floatColumn.getFloat(0), 0.001);
-    Assert.assertEquals(9.0, floatColumn.getFloat(1), 0.001);
+    FloatColumn floatColumn2 = (FloatColumn) floatColumn1.subColumn(3);
+    Assert.assertEquals(2, floatColumn2.getPositionCount());
+    Assert.assertEquals(8.0, floatColumn2.getFloat(0), 0.001);
+    Assert.assertEquals(9.0, floatColumn2.getFloat(1), 0.001);
+
+    Assert.assertSame(floatColumn1.getFloats(), floatColumn2.getFloats());
+  }
+
+  @Test
+  public void floatColumnSubColumnCopyTest() {
+    FloatColumnBuilder columnBuilder = new FloatColumnBuilder(null, 10);
+    for (int i = 0; i < 10; i++) {
+      columnBuilder.writeFloat(i);
+    }
+    FloatColumn floatColumn1 = (FloatColumn) columnBuilder.build();
+    floatColumn1 = (FloatColumn) floatColumn1.subColumnCopy(5);
+    Assert.assertEquals(5, floatColumn1.getPositionCount());
+    Assert.assertEquals(5.0, floatColumn1.getFloat(0), 0.001);
+    Assert.assertEquals(9.0, floatColumn1.getFloat(4), 0.001);
+
+    FloatColumn floatColumn2 = (FloatColumn) floatColumn1.subColumnCopy(3);
+    Assert.assertEquals(2, floatColumn2.getPositionCount());
+    Assert.assertEquals(8.0, floatColumn2.getFloat(0), 0.001);
+    Assert.assertEquals(9.0, floatColumn2.getFloat(1), 0.001);
+
+    Assert.assertNotSame(floatColumn1.getFloats(), floatColumn2.getFloats());
   }
 
   @Test
@@ -140,16 +251,38 @@
     for (int i = 0; i < 10; i++) {
       columnBuilder.writeInt(i);
     }
-    IntColumn intColumn = (IntColumn) columnBuilder.build();
-    intColumn = (IntColumn) intColumn.subColumn(5);
-    Assert.assertEquals(5, intColumn.getPositionCount());
-    Assert.assertEquals(5, intColumn.getInt(0));
-    Assert.assertEquals(9, intColumn.getInt(4));
+    IntColumn intColumn1 = (IntColumn) columnBuilder.build();
+    intColumn1 = (IntColumn) intColumn1.subColumn(5);
+    Assert.assertEquals(5, intColumn1.getPositionCount());
+    Assert.assertEquals(5, intColumn1.getInt(0));
+    Assert.assertEquals(9, intColumn1.getInt(4));
 
-    intColumn = (IntColumn) intColumn.subColumn(3);
-    Assert.assertEquals(2, intColumn.getPositionCount());
-    Assert.assertEquals(8, intColumn.getInt(0));
-    Assert.assertEquals(9, intColumn.getInt(1));
+    IntColumn intColumn2 = (IntColumn) intColumn1.subColumn(3);
+    Assert.assertEquals(2, intColumn2.getPositionCount());
+    Assert.assertEquals(8, intColumn2.getInt(0));
+    Assert.assertEquals(9, intColumn2.getInt(1));
+
+    Assert.assertSame(intColumn1.getInts(), intColumn2.getInts());
+  }
+
+  @Test
+  public void intColumnSubColumnCopyTest() {
+    IntColumnBuilder columnBuilder = new IntColumnBuilder(null, 10);
+    for (int i = 0; i < 10; i++) {
+      columnBuilder.writeInt(i);
+    }
+    IntColumn intColumn1 = (IntColumn) columnBuilder.build();
+    intColumn1 = (IntColumn) intColumn1.subColumnCopy(5);
+    Assert.assertEquals(5, intColumn1.getPositionCount());
+    Assert.assertEquals(5, intColumn1.getInt(0));
+    Assert.assertEquals(9, intColumn1.getInt(4));
+
+    IntColumn intColumn2 = (IntColumn) intColumn1.subColumnCopy(3);
+    Assert.assertEquals(2, intColumn2.getPositionCount());
+    Assert.assertEquals(8, intColumn2.getInt(0));
+    Assert.assertEquals(9, intColumn2.getInt(1));
+
+    Assert.assertNotSame(intColumn1.getInts(), intColumn2.getInts());
   }
 
   @Test
@@ -158,16 +291,38 @@
     for (int i = 0; i < 10; i++) {
       columnBuilder.writeLong(i);
     }
-    LongColumn longColumn = (LongColumn) columnBuilder.build();
-    longColumn = (LongColumn) longColumn.subColumn(5);
-    Assert.assertEquals(5, longColumn.getPositionCount());
-    Assert.assertEquals(5, longColumn.getLong(0));
-    Assert.assertEquals(9, longColumn.getLong(4));
+    LongColumn longColumn1 = (LongColumn) columnBuilder.build();
+    longColumn1 = (LongColumn) longColumn1.subColumn(5);
+    Assert.assertEquals(5, longColumn1.getPositionCount());
+    Assert.assertEquals(5, longColumn1.getLong(0));
+    Assert.assertEquals(9, longColumn1.getLong(4));
 
-    longColumn = (LongColumn) longColumn.subColumn(3);
-    Assert.assertEquals(2, longColumn.getPositionCount());
-    Assert.assertEquals(8, longColumn.getLong(0));
-    Assert.assertEquals(9, longColumn.getLong(1));
+    LongColumn longColumn2 = (LongColumn) longColumn1.subColumn(3);
+    Assert.assertEquals(2, longColumn2.getPositionCount());
+    Assert.assertEquals(8, longColumn2.getLong(0));
+    Assert.assertEquals(9, longColumn2.getLong(1));
+
+    Assert.assertSame(longColumn1.getLongs(), longColumn2.getLongs());
+  }
+
+  @Test
+  public void longColumnSubColumnCopyTest() {
+    LongColumnBuilder columnBuilder = new LongColumnBuilder(null, 10);
+    for (int i = 0; i < 10; i++) {
+      columnBuilder.writeLong(i);
+    }
+    LongColumn longColumn1 = (LongColumn) columnBuilder.build();
+    longColumn1 = (LongColumn) longColumn1.subColumnCopy(5);
+    Assert.assertEquals(5, longColumn1.getPositionCount());
+    Assert.assertEquals(5, longColumn1.getLong(0));
+    Assert.assertEquals(9, longColumn1.getLong(4));
+
+    LongColumn longColumn2 = (LongColumn) longColumn1.subColumnCopy(3);
+    Assert.assertEquals(2, longColumn2.getPositionCount());
+    Assert.assertEquals(8, longColumn2.getLong(0));
+    Assert.assertEquals(9, longColumn2.getLong(1));
+
+    Assert.assertNotSame(longColumn1.getLongs(), longColumn2.getLongs());
   }
 
   @Test
@@ -195,4 +350,20 @@
     Assert.assertEquals(1, column.getLong(0));
     Assert.assertEquals(1, column.getLong(1));
   }
+
+  @Test
+  public void runLengthEncodedColumnSubColumnCopyTest() {
+    LongColumnBuilder longColumnBuilder = new LongColumnBuilder(null, 1);
+    longColumnBuilder.writeLong(1);
+    RunLengthEncodedColumn column = new RunLengthEncodedColumn(longColumnBuilder.build(), 10);
+    column = (RunLengthEncodedColumn) column.subColumnCopy(5);
+    Assert.assertEquals(5, column.getPositionCount());
+    Assert.assertEquals(1, column.getLong(0));
+    Assert.assertEquals(1, column.getLong(4));
+
+    column = (RunLengthEncodedColumn) column.subColumnCopy(3);
+    Assert.assertEquals(2, column.getPositionCount());
+    Assert.assertEquals(1, column.getLong(0));
+    Assert.assertEquals(1, column.getLong(1));
+  }
 }