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

haonan pushed a commit to branch rc/2.2.1
in repository https://gitbox.apache.org/repos/asf/tsfile.git

commit add5b3b3a9944839d8567f0a62a7a392b39c6dd2
Author: libo <[email protected]>
AuthorDate: Wed Sep 3 11:48:38 2025 +0800

    Alter column other type to string type (#588)
    
    * Resolve may happen the problem that type conversion.
    
    * Format code.
    
    * Fix code.
    
    * Fix code.
    
    * Modify functions related type transfer in every operators class via 
template
    
    * Support for what other type transfer to text/string type.
    
    * Fix
    
    * Allow modify value of date type, format to LocalDate result.
    
    * Resolve the problem that BinaryColumnBuilder wrong use string of int type 
to transfer string of date type.
    
    * Resolve the problem that the type of  statistics don't match
    
    * Fix
    
    * Fix bug.
    
    * Format code.
    
    * Fix IT test.
    
    * Fix IT bug.
    
    * Adjust some problems.
    
    * Format code.
---
 .../java/org/apache/tsfile/enums/TSDataType.java   |  98 +++++-
 .../codegen/templates/FilterOperatorsTemplate.ftl  | 356 +++++++++++++++++++--
 .../file/metadata/statistics/Statistics.java       |  51 ++-
 .../common/block/column/BinaryColumnBuilder.java   |  30 ++
 .../org/apache/tsfile/read/reader/IPageReader.java |   2 +
 .../reader/page/AbstractAlignedPageReader.java     |   5 +
 .../apache/tsfile/read/reader/page/PageReader.java |   5 +
 .../tsfile/read/reader/page/ValuePageReader.java   |  41 ++-
 .../java/org/apache/tsfile/utils/TypeCastTest.java |  81 ++++-
 9 files changed, 628 insertions(+), 41 deletions(-)

diff --git a/java/common/src/main/java/org/apache/tsfile/enums/TSDataType.java 
b/java/common/src/main/java/org/apache/tsfile/enums/TSDataType.java
index cf17aa04..492d1bab 100644
--- a/java/common/src/main/java/org/apache/tsfile/enums/TSDataType.java
+++ b/java/common/src/main/java/org/apache/tsfile/enums/TSDataType.java
@@ -19,6 +19,7 @@
 
 package org.apache.tsfile.enums;
 
+import org.apache.tsfile.utils.Binary;
 import org.apache.tsfile.write.UnSupportedDataTypeException;
 
 import java.io.DataOutputStream;
@@ -26,6 +27,7 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.EnumMap;
@@ -99,6 +101,14 @@ public enum TSDataType {
 
     Set<TSDataType> textCompatibleTypes = new HashSet<>();
     textCompatibleTypes.add(STRING);
+    textCompatibleTypes.add(INT32);
+    textCompatibleTypes.add(INT64);
+    textCompatibleTypes.add(FLOAT);
+    textCompatibleTypes.add(DOUBLE);
+    textCompatibleTypes.add(BOOLEAN);
+    textCompatibleTypes.add(BLOB);
+    textCompatibleTypes.add(DATE);
+    textCompatibleTypes.add(TIMESTAMP);
     compatibleTypes.put(TEXT, textCompatibleTypes);
 
     compatibleTypes.put(VECTOR, Collections.emptySet());
@@ -119,6 +129,15 @@ public enum TSDataType {
 
     Set<TSDataType> stringCompatibleTypes = new HashSet<>();
     stringCompatibleTypes.add(TEXT);
+    // add
+    stringCompatibleTypes.add(INT32);
+    stringCompatibleTypes.add(INT64);
+    stringCompatibleTypes.add(FLOAT);
+    stringCompatibleTypes.add(DOUBLE);
+    stringCompatibleTypes.add(BOOLEAN);
+    stringCompatibleTypes.add(BLOB);
+    stringCompatibleTypes.add(DATE);
+    stringCompatibleTypes.add(TIMESTAMP);
     compatibleTypes.put(STRING, stringCompatibleTypes);
   }
 
@@ -232,6 +251,17 @@ public enum TSDataType {
       case TEXT:
         if (sourceType == TSDataType.TEXT || sourceType == TSDataType.STRING) {
           return value;
+        } else if (sourceType == TSDataType.INT32
+            || sourceType == TSDataType.INT64
+            || sourceType == TSDataType.FLOAT
+            || sourceType == TSDataType.DOUBLE
+            || sourceType == TSDataType.BOOLEAN
+            || sourceType == TSDataType.TIMESTAMP) {
+          return new Binary(String.valueOf(value), StandardCharsets.UTF_8);
+        } else if (sourceType == TSDataType.DATE) {
+          return new Binary(getDateStringValue((int) value), 
StandardCharsets.UTF_8);
+        } else if (sourceType == TSDataType.BLOB) {
+          return new Binary(value.toString(), StandardCharsets.UTF_8);
         } else {
           break;
         }
@@ -262,6 +292,17 @@ public enum TSDataType {
       case STRING:
         if (sourceType == TSDataType.STRING || sourceType == TSDataType.TEXT) {
           return value;
+        } else if (sourceType == TSDataType.INT32
+            || sourceType == TSDataType.INT64
+            || sourceType == TSDataType.FLOAT
+            || sourceType == TSDataType.DOUBLE
+            || sourceType == TSDataType.BOOLEAN
+            || sourceType == TSDataType.TIMESTAMP) {
+          return new Binary(String.valueOf(value), StandardCharsets.UTF_8);
+        } else if (sourceType == TSDataType.DATE) {
+          return new Binary(getDateStringValue((int) value), 
StandardCharsets.UTF_8);
+        } else if (sourceType == TSDataType.BLOB) {
+          return new Binary(value.toString(), StandardCharsets.UTF_8);
         } else {
           break;
         }
@@ -331,12 +372,6 @@ public enum TSDataType {
         } else {
           break;
         }
-      case TEXT:
-        if (sourceType == TSDataType.TEXT || sourceType == STRING) {
-          return array;
-        } else {
-          break;
-        }
       case TIMESTAMP:
         if (sourceType == TSDataType.TIMESTAMP) {
           return array;
@@ -361,9 +396,54 @@ public enum TSDataType {
         } else {
           break;
         }
+      case TEXT:
       case STRING:
-        if (sourceType == TSDataType.STRING || sourceType == TSDataType.TEXT) {
+        if (sourceType == TSDataType.STRING
+            || sourceType == TSDataType.TEXT
+            || sourceType == TSDataType.BLOB) {
           return array;
+        } else if (sourceType == TSDataType.INT32) {
+          int[] tmp = (int[]) array;
+          Binary[] result = new Binary[tmp.length];
+          for (int i = 0; i < tmp.length; i++) {
+            result[i] = new Binary(String.valueOf(tmp[i]), 
StandardCharsets.UTF_8);
+          }
+          return result;
+        } else if (sourceType == TSDataType.DATE) {
+          int[] tmp = (int[]) array;
+          Binary[] result = new Binary[tmp.length];
+          for (int i = 0; i < tmp.length; i++) {
+            result[i] = new Binary(TSDataType.getDateStringValue(tmp[i]), 
StandardCharsets.UTF_8);
+          }
+          return result;
+        } else if (sourceType == TSDataType.INT64 || sourceType == 
TSDataType.TIMESTAMP) {
+          long[] tmp = (long[]) array;
+          Binary[] result = new Binary[tmp.length];
+          for (int i = 0; i < tmp.length; i++) {
+            result[i] = new Binary(String.valueOf(tmp[i]), 
StandardCharsets.UTF_8);
+          }
+          return result;
+        } else if (sourceType == TSDataType.FLOAT) {
+          float[] tmp = (float[]) array;
+          Binary[] result = new Binary[tmp.length];
+          for (int i = 0; i < tmp.length; i++) {
+            result[i] = new Binary(String.valueOf(tmp[i]), 
StandardCharsets.UTF_8);
+          }
+          return result;
+        } else if (sourceType == TSDataType.DOUBLE) {
+          double[] tmp = (double[]) array;
+          Binary[] result = new Binary[tmp.length];
+          for (int i = 0; i < tmp.length; i++) {
+            result[i] = new Binary(String.valueOf(tmp[i]), 
StandardCharsets.UTF_8);
+          }
+          return result;
+        } else if (sourceType == TSDataType.BOOLEAN) {
+          boolean[] tmp = (boolean[]) array;
+          Binary[] result = new Binary[tmp.length];
+          for (int i = 0; i < tmp.length; i++) {
+            result[i] = new Binary(String.valueOf(tmp[i]), 
StandardCharsets.UTF_8);
+          }
+          return result;
         } else {
           break;
         }
@@ -487,4 +567,8 @@ public enum TSDataType {
   public boolean isBinary() {
     return this == TEXT || this == STRING || this == BLOB;
   }
+
+  public static String getDateStringValue(int value) {
+    return String.format("%04d-%02d-%02d", value / 10000, (value % 10000) / 
100, value % 100);
+  }
 }
diff --git a/java/tsfile/src/main/codegen/templates/FilterOperatorsTemplate.ftl 
b/java/tsfile/src/main/codegen/templates/FilterOperatorsTemplate.ftl
index 0fe475d1..7e39b361 100644
--- a/java/tsfile/src/main/codegen/templates/FilterOperatorsTemplate.ftl
+++ b/java/tsfile/src/main/codegen/templates/FilterOperatorsTemplate.ftl
@@ -42,6 +42,9 @@ import java.io.DataOutputStream;
 import java.io.IOException;
 import java.io.Serializable;
 import java.nio.ByteBuffer;
+<#if filter.dataType == "Binary">
+import java.nio.charset.StandardCharsets;
+</#if>
 <#if filter.dataType != "boolean">
 import java.util.Collections;
 </#if>
@@ -137,8 +140,15 @@ public final class ${className} {
 
     @Override
     public boolean valueSatisfy(Object value){
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary" || 
filter.javaBoxName == "String">
+      <#if filter.dataType == "boolean" || filter.javaBoxName == "String">
       return valueSatisfy((${filter.dataType}) value);
+      <#elseif filter.dataType == "Binary">
+      if(value instanceof Binary){
+        return valueSatisfy((${filter.dataType}) value);
+      }
+      else{
+        return valueSatisfy(new ${filter.dataType}(String.valueOf(value), 
StandardCharsets.UTF_8));
+      }
       <#else>
       return valueSatisfy(((Number) value).${filter.dataType}Value());
       </#if>
@@ -156,7 +166,7 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean canSkip(Statistics<? extends Serializable> statistics) {
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+      <#if filter.dataType == "boolean">
         <#if filter.javaBoxName == "String">
       if(statistics.isEmpty()){
         return false;
@@ -166,6 +176,22 @@ public final class ${className} {
         <#else>
       return false;
         </#if>
+      <#elseif filter.dataType == "Binary">
+        <#if filter.javaBoxName == "String">
+      if(statistics.isEmpty()){
+        return false;
+      }
+      if((statistics.getMinValue() instanceof Binary) && 
(statistics.getMaxValue() instanceof Binary)){
+        return constant.compareTo((${filter.dataType}) 
statistics.getMinValue()) < 0
+            || constant.compareTo((${filter.dataType}) 
statistics.getMaxValue()) > 0;
+      }
+      else{
+        return constant.compareTo(new 
${filter.dataType}(String.valueOf(statistics.getMinValue()), 
StandardCharsets.UTF_8)) < 0
+            || constant.compareTo(new 
${filter.dataType}(String.valueOf(statistics.getMaxValue()), 
StandardCharsets.UTF_8)) > 0;
+      }
+        <#else>
+      return false;
+        </#if>
       <#else>
       // drop if value < min || value > max
       if(statistics.isEmpty()){
@@ -179,7 +205,7 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean allSatisfy(Statistics<? extends Serializable> statistics) {
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+      <#if filter.dataType == "boolean">
         <#if filter.javaBoxName == "String">
       if(statistics.isEmpty()){
         return false;
@@ -189,6 +215,22 @@ public final class ${className} {
         <#else>
       return false;
         </#if>
+      <#elseif filter.dataType == "Binary">
+        <#if filter.javaBoxName == "String">
+      if(statistics.isEmpty()){
+        return false;
+      }
+      if((statistics.getMinValue() instanceof Binary) && 
(statistics.getMaxValue() instanceof Binary)){
+        return constant.compareTo((${filter.dataType}) 
statistics.getMinValue()) == 0
+            && constant.compareTo((${filter.dataType}) 
statistics.getMaxValue()) == 0;
+      }
+      else{
+        return constant.compareTo(new 
${filter.dataType}(String.valueOf(statistics.getMinValue()), 
StandardCharsets.UTF_8)) == 0
+            && constant.compareTo(new 
${filter.dataType}(String.valueOf(statistics.getMaxValue()), 
StandardCharsets.UTF_8)) == 0;
+      }
+        <#else>
+      return false;
+        </#if>
       <#else>
       // drop if value < min || value > max
       if(statistics.isEmpty()){
@@ -222,8 +264,14 @@ public final class ${className} {
 
     @Override
     public boolean valueSatisfy(Object value){
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary" || 
filter.javaBoxName == "String">
+      <#if filter.dataType == "boolean" || filter.javaBoxName == "String">
       return valueSatisfy((${filter.dataType}) value);
+      <#elseif filter.dataType == "Binary">
+      if(value instanceof Binary){
+        return valueSatisfy((${filter.dataType}) value);
+      } else {
+        return valueSatisfy(new ${filter.dataType}(String.valueOf(value), 
StandardCharsets.UTF_8));
+      }
       <#else>
       return valueSatisfy(((Number) value).${filter.dataType}Value());
       </#if>
@@ -241,7 +289,7 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean canSkip(Statistics<? extends Serializable> statistics) {
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+      <#if filter.dataType == "boolean">
         <#if filter.javaBoxName == "String">
       if(statistics.isEmpty()){
         return false;
@@ -251,6 +299,22 @@ public final class ${className} {
         <#else>
       return false;
         </#if>
+      <#elseif filter.dataType == "Binary">
+        <#if filter.javaBoxName == "String">
+      if(statistics.isEmpty()){
+        return false;
+      }
+      if((statistics.getMinValue() instanceof Binary) && 
(statistics.getMaxValue() instanceof Binary)){
+        return constant.compareTo((${filter.dataType}) 
statistics.getMinValue()) == 0
+            && constant.compareTo((${filter.dataType}) 
statistics.getMaxValue()) == 0;
+      }
+      else{
+        return constant.compareTo(new 
${filter.dataType}(String.valueOf(statistics.getMinValue()), 
StandardCharsets.UTF_8)) == 0
+            && constant.compareTo(new 
${filter.dataType}(String.valueOf(statistics.getMaxValue()), 
StandardCharsets.UTF_8)) == 0;
+      }
+        <#else>
+      return false;
+        </#if>
       <#else>
       // drop if value < min || value > max
       if(statistics.isEmpty()){
@@ -265,7 +329,7 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean allSatisfy(Statistics<? extends Serializable> statistics) {
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+      <#if filter.dataType == "boolean">
         <#if filter.javaBoxName == "String">
       if(statistics.isEmpty()){
         return false;
@@ -275,6 +339,22 @@ public final class ${className} {
         <#else>
       return false;
         </#if>
+      <#elseif filter.dataType == "Binary">
+        <#if filter.javaBoxName == "String">
+      if(statistics.isEmpty()){
+        return false;
+      }
+      if((statistics.getMinValue() instanceof Binary) && 
(statistics.getMaxValue() instanceof Binary)){
+        return constant.compareTo((${filter.dataType}) 
statistics.getMinValue()) < 0
+            || constant.compareTo((${filter.dataType}) 
statistics.getMaxValue()) > 0;
+      }
+      else{
+        return constant.compareTo(new 
${filter.dataType}(String.valueOf(statistics.getMinValue()), 
StandardCharsets.UTF_8)) < 0
+            || constant.compareTo(new 
${filter.dataType}(String.valueOf(statistics.getMaxValue()), 
StandardCharsets.UTF_8)) > 0;
+      }
+        <#else>
+      return false;
+        </#if>
       <#else>
       if(statistics.isEmpty()){
         return false;
@@ -308,8 +388,14 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean valueSatisfy(Object value){
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary" || 
filter.javaBoxName == "String">
+      <#if filter.dataType == "boolean" || filter.javaBoxName == "String">
       return valueSatisfy((${filter.dataType}) value);
+      <#elseif filter.dataType == "Binary">
+      if(value instanceof Binary){
+        return valueSatisfy((${filter.dataType}) value);
+      } else {
+        return valueSatisfy(new ${filter.dataType}(String.valueOf(value), 
StandardCharsets.UTF_8));
+      }
       <#else>
       return valueSatisfy(((Number) value).${filter.dataType}Value());
       </#if>
@@ -329,7 +415,7 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean canSkip(Statistics<? extends Serializable> statistics) {
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+      <#if filter.dataType == "boolean">
         <#if filter.javaBoxName == "String">
       if(statistics.isEmpty()){
         return false;
@@ -338,6 +424,20 @@ public final class ${className} {
         <#else>
       return false;
         </#if>
+      <#elseif filter.dataType == "Binary">
+        <#if filter.javaBoxName == "String">
+      if(statistics.isEmpty()){
+        return false;
+      }
+      if(statistics.getMinValue() instanceof Binary) {
+        return constant.compareTo((${filter.dataType}) 
statistics.getMinValue()) <= 0;
+      }
+      else{
+        return constant.compareTo(new 
${filter.dataType}(String.valueOf(statistics.getMinValue()), 
StandardCharsets.UTF_8)) <= 0;
+      }
+        <#else>
+      return false;
+        </#if>
       <#else>
       // drop if value < min || value > max
       if(statistics.isEmpty()){
@@ -351,7 +451,7 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean allSatisfy(Statistics<? extends Serializable> statistics) {
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+      <#if filter.dataType == "boolean">
         <#if filter.javaBoxName == "String">
       if(statistics.isEmpty()){
         return false;
@@ -360,6 +460,20 @@ public final class ${className} {
         <#else>
       return false;
         </#if>
+      <#elseif filter.dataType == "Binary">
+        <#if filter.javaBoxName == "String">
+      if(statistics.isEmpty()){
+        return false;
+      }
+      if(statistics.getMaxValue() instanceof Binary){
+        return constant.compareTo((${filter.dataType}) 
statistics.getMaxValue()) > 0;
+      }
+      else{
+        return constant.compareTo(new 
${filter.dataType}(String.valueOf(statistics.getMaxValue()), 
StandardCharsets.UTF_8)) > 0;
+      }
+        <#else>
+      return false;
+        </#if>
       <#else>
       if(statistics.isEmpty()){
         return false;
@@ -392,8 +506,14 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean valueSatisfy(Object value){
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary" || 
filter.javaBoxName == "String">
+      <#if filter.dataType == "boolean" || filter.javaBoxName == "String">
       return valueSatisfy((${filter.dataType}) value);
+      <#elseif filter.dataType == "Binary">
+      if(value instanceof Binary){
+        return valueSatisfy((${filter.dataType}) value);
+      } else {
+        return valueSatisfy(new ${filter.dataType}(String.valueOf(value), 
StandardCharsets.UTF_8));
+      }
       <#else>
       return valueSatisfy(((Number) value).${filter.dataType}Value());
       </#if>
@@ -413,7 +533,7 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean canSkip(Statistics<? extends Serializable> statistics) {
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+      <#if filter.dataType == "boolean">
         <#if filter.javaBoxName == "String">
       if(statistics.isEmpty()){
         return false;
@@ -422,6 +542,20 @@ public final class ${className} {
         <#else>
       return false;
         </#if>
+      <#elseif filter.dataType == "Binary">
+        <#if filter.javaBoxName == "String">
+      if(statistics.isEmpty()){
+        return false;
+      }
+      if(statistics.getMinValue() instanceof Binary) {
+        return constant.compareTo((${filter.dataType}) 
statistics.getMinValue()) < 0;
+      }
+      else{
+        return constant.compareTo(new 
${filter.dataType}(String.valueOf(statistics.getMinValue()), 
StandardCharsets.UTF_8)) < 0;
+      }
+        <#else>
+      return false;
+        </#if>
       <#else>
       // drop if value < min || value > max
       if(statistics.isEmpty()){
@@ -435,7 +569,7 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean allSatisfy(Statistics<? extends Serializable> statistics) {
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+      <#if filter.dataType == "boolean">
         <#if filter.javaBoxName == "String">
       if(statistics.isEmpty()){
         return false;
@@ -444,6 +578,20 @@ public final class ${className} {
         <#else>
       return false;
         </#if>
+      <#elseif filter.dataType == "Binary">
+        <#if filter.javaBoxName == "String">
+      if(statistics.isEmpty()){
+        return false;
+      }
+      if(statistics.getMaxValue() instanceof Binary){
+        return constant.compareTo((${filter.dataType}) 
statistics.getMaxValue()) >= 0;
+      }
+      else{
+        return constant.compareTo(new 
${filter.dataType}(String.valueOf(statistics.getMaxValue()), 
StandardCharsets.UTF_8)) >= 0;
+      }
+        <#else>
+      return false;
+        </#if>
       <#else>
       if(statistics.isEmpty()){
         return false;
@@ -476,8 +624,14 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean valueSatisfy(Object value){
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary" || 
filter.javaBoxName == "String">
+      <#if filter.dataType == "boolean" || filter.javaBoxName == "String">
       return valueSatisfy((${filter.dataType}) value);
+      <#elseif filter.dataType == "Binary">
+      if(value instanceof Binary){
+        return valueSatisfy((${filter.dataType}) value);
+      } else {
+        return valueSatisfy(new ${filter.dataType}(String.valueOf(value), 
StandardCharsets.UTF_8));
+      }
       <#else>
       return valueSatisfy(((Number) value).${filter.dataType}Value());
       </#if>
@@ -497,7 +651,7 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean canSkip(Statistics<? extends Serializable> statistics) {
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+      <#if filter.dataType == "boolean">
         <#if filter.javaBoxName == "String">
       if(statistics.isEmpty()){
         return false;
@@ -506,6 +660,20 @@ public final class ${className} {
         <#else>
       return false;
         </#if>
+      <#elseif filter.dataType == "Binary">
+        <#if filter.javaBoxName == "String">
+      if(statistics.isEmpty()){
+        return false;
+      }
+      if(statistics.getMaxValue() instanceof Binary) {
+        return constant.compareTo((${filter.dataType}) 
statistics.getMaxValue()) >= 0;
+      }
+      else{
+        return constant.compareTo(new 
${filter.dataType}(String.valueOf(statistics.getMaxValue()), 
StandardCharsets.UTF_8)) >= 0;
+      }
+        <#else>
+      return false;
+        </#if>
       <#else>
       // drop if value < min || value > max
       if(statistics.isEmpty()){
@@ -519,7 +687,7 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean allSatisfy(Statistics<? extends Serializable> statistics) {
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+      <#if filter.dataType == "boolean">
         <#if filter.javaBoxName == "String">
       if(statistics.isEmpty()){
         return false;
@@ -528,6 +696,20 @@ public final class ${className} {
         <#else>
       return false;
         </#if>
+      <#elseif filter.dataType == "Binary">
+        <#if filter.javaBoxName == "String">
+      if(statistics.isEmpty()){
+        return false;
+      }
+      if(statistics.getMinValue() instanceof Binary){
+        return constant.compareTo((${filter.dataType}) 
statistics.getMinValue()) < 0;
+      }
+      else{
+        return constant.compareTo(new 
${filter.dataType}(String.valueOf(statistics.getMinValue()), 
StandardCharsets.UTF_8)) < 0;
+      }
+        <#else>
+      return false;
+        </#if>
       <#else>
       if(statistics.isEmpty()){
         return false;
@@ -560,8 +742,14 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean valueSatisfy(Object value){
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary" || 
filter.javaBoxName == "String">
+      <#if filter.dataType == "boolean" || filter.javaBoxName == "String">
       return valueSatisfy((${filter.dataType}) value);
+      <#elseif filter.dataType == "Binary">
+      if(value instanceof Binary){
+        return valueSatisfy((${filter.dataType}) value);
+      } else {
+        return valueSatisfy(new ${filter.dataType}(String.valueOf(value), 
StandardCharsets.UTF_8));
+      }
       <#else>
       return valueSatisfy(((Number) value).${filter.dataType}Value());
       </#if>
@@ -581,7 +769,7 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean canSkip(Statistics<? extends Serializable> statistics) {
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+      <#if filter.dataType == "boolean">
         <#if filter.javaBoxName == "String">
       if(statistics.isEmpty()){
         return false;
@@ -590,6 +778,20 @@ public final class ${className} {
         <#else>
       return false;
         </#if>
+      <#elseif filter.dataType == "Binary">
+        <#if filter.javaBoxName == "String">
+      if(statistics.isEmpty()){
+        return false;
+      }
+      if(statistics.getMaxValue() instanceof Binary) {
+        return constant.compareTo((${filter.dataType}) 
statistics.getMaxValue()) > 0;
+      }
+      else{
+        return constant.compareTo(new 
${filter.dataType}(String.valueOf(statistics.getMaxValue()), 
StandardCharsets.UTF_8)) > 0;
+      }
+        <#else>
+      return false;
+        </#if>
       <#else>
       // drop if value < min || value > max
       if(statistics.isEmpty()){
@@ -603,7 +805,7 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean allSatisfy(Statistics<? extends Serializable> statistics) {
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+      <#if filter.dataType == "boolean">
         <#if filter.javaBoxName == "String">
       if(statistics.isEmpty()){
         return false;
@@ -612,6 +814,20 @@ public final class ${className} {
         <#else>
       return false;
         </#if>
+      <#elseif filter.dataType == "Binary">
+        <#if filter.javaBoxName == "String">
+      if(statistics.isEmpty()){
+        return false;
+      }
+      if(statistics.getMinValue() instanceof Binary){
+        return constant.compareTo((${filter.dataType}) 
statistics.getMinValue()) <= 0;
+      }
+      else{
+        return constant.compareTo(new 
${filter.dataType}(String.valueOf(statistics.getMinValue()), 
StandardCharsets.UTF_8)) <= 0;
+      }
+        <#else>
+      return false;
+        </#if>
       <#else>
       if(statistics.isEmpty()){
         return false;
@@ -712,8 +928,14 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean valueSatisfy(Object value){
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary" || 
filter.javaBoxName == "String">
+      <#if filter.dataType == "boolean" || filter.javaBoxName == "String">
       return valueSatisfy((${filter.dataType}) value);
+      <#elseif filter.dataType == "Binary">
+      if(value instanceof Binary){
+        return valueSatisfy((${filter.dataType}) value);
+      } else {
+        return valueSatisfy(new ${filter.dataType}(String.valueOf(value), 
StandardCharsets.UTF_8));
+      }
       <#else>
       return valueSatisfy(((Number) value).${filter.dataType}Value());
       </#if>
@@ -735,7 +957,7 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean canSkip(Statistics<? extends Serializable> statistics) {
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+      <#if filter.dataType == "boolean">
         <#if filter.javaBoxName == "String">
       if(statistics.isEmpty()){
         return false;
@@ -745,6 +967,22 @@ public final class ${className} {
         <#else>
       return false;
         </#if>
+      <#elseif filter.dataType == "Binary">
+        <#if filter.javaBoxName == "String">
+      if(statistics.isEmpty()){
+        return false;
+      }
+      if((statistics.getMaxValue() instanceof Binary) && 
(statistics.getMinValue() instanceof Binary)) {
+        return ((${filter.dataType}) statistics.getMaxValue()).compareTo(min) 
< 0
+            || ((${filter.dataType}) statistics.getMinValue()).compareTo(max) 
> 0;
+      }
+      else{
+        return (new 
${filter.dataType}(String.valueOf(statistics.getMaxValue()), 
StandardCharsets.UTF_8)).compareTo(min) < 0
+            || (new 
${filter.dataType}(String.valueOf(statistics.getMinValue()), 
StandardCharsets.UTF_8)).compareTo(max) > 0;
+      }
+        <#else>
+      return false;
+        </#if>
       <#else>
       // drop if value < min || value > max
       if(statistics.isEmpty()){
@@ -758,7 +996,7 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean allSatisfy(Statistics<? extends Serializable> statistics) {
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+      <#if filter.dataType == "boolean">
         <#if filter.javaBoxName == "String">
       if(statistics.isEmpty()){
         return false;
@@ -768,6 +1006,22 @@ public final class ${className} {
         <#else>
       return false;
         </#if>
+      <#elseif filter.dataType == "Binary">
+        <#if filter.javaBoxName == "String">
+      if(statistics.isEmpty()){
+        return false;
+      }
+      if((statistics.getMinValue() instanceof Binary) && 
(statistics.getMaxValue() instanceof Binary)){
+        return ((${filter.dataType}) statistics.getMinValue()).compareTo(min) 
>= 0
+            && ((${filter.dataType}) statistics.getMaxValue()).compareTo(max) 
<= 0;
+      }
+      else{
+        return (new 
${filter.dataType}(String.valueOf(statistics.getMinValue()), 
StandardCharsets.UTF_8)).compareTo(min) >= 0
+            && (new 
${filter.dataType}(String.valueOf(statistics.getMaxValue()), 
StandardCharsets.UTF_8)).compareTo(max) <= 0;
+      }
+        <#else>
+      return false;
+        </#if>
       <#else>
       if(statistics.isEmpty()){
         return false;
@@ -801,8 +1055,14 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean valueSatisfy(Object value){
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary" || 
filter.javaBoxName == "String">
+      <#if filter.dataType == "boolean" || filter.javaBoxName == "String">
       return valueSatisfy((${filter.dataType}) value);
+      <#elseif filter.dataType == "Binary">
+      if(value instanceof Binary){
+        return valueSatisfy((${filter.dataType}) value);
+      } else {
+        return valueSatisfy(new ${filter.dataType}(String.valueOf(value), 
StandardCharsets.UTF_8));
+      }
       <#else>
       return valueSatisfy(((Number) value).${filter.dataType}Value());
       </#if>
@@ -823,7 +1083,7 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean canSkip(Statistics<? extends Serializable> statistics) {
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+      <#if filter.dataType == "boolean">
         <#if filter.javaBoxName == "String">
       if(statistics.isEmpty()){
         return false;
@@ -833,6 +1093,22 @@ public final class ${className} {
         <#else>
       return false;
         </#if>
+      <#elseif filter.dataType == "Binary">
+        <#if filter.javaBoxName == "String">
+      if(statistics.isEmpty()){
+        return false;
+      }
+      if((statistics.getMinValue() instanceof Binary) && 
(statistics.getMaxValue() instanceof Binary)) {
+        return ((${filter.dataType}) statistics.getMinValue()).compareTo(min) 
>= 0
+            && ((${filter.dataType}) statistics.getMaxValue()).compareTo(max) 
<= 0;
+      }
+      else{
+        return (new 
${filter.dataType}(String.valueOf(statistics.getMinValue()), 
StandardCharsets.UTF_8)).compareTo(min) >= 0
+            && (new 
${filter.dataType}(String.valueOf(statistics.getMaxValue()), 
StandardCharsets.UTF_8)).compareTo(max) <= 0;
+      }
+        <#else>
+      return false;
+        </#if>
       <#else>
       // drop if value < min || value > max
       if(statistics.isEmpty()){
@@ -846,7 +1122,7 @@ public final class ${className} {
     @Override
     @SuppressWarnings("unchecked")
     public boolean allSatisfy(Statistics<? extends Serializable> statistics) {
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+      <#if filter.dataType == "boolean">
         <#if filter.javaBoxName == "String">
       if(statistics.isEmpty()){
         return false;
@@ -856,6 +1132,22 @@ public final class ${className} {
         <#else>
       return false;
         </#if>
+      <#elseif filter.dataType == "Binary">
+        <#if filter.javaBoxName == "String">
+      if(statistics.isEmpty()){
+        return false;
+      }
+      if((statistics.getMinValue() instanceof Binary) && 
(statistics.getMaxValue() instanceof Binary)){
+        return ((${filter.dataType}) statistics.getMinValue()).compareTo(max) 
> 0
+            || ((${filter.dataType}) statistics.getMaxValue()).compareTo(min) 
< 0;
+      }
+      else{
+        return (new 
${filter.dataType}(String.valueOf(statistics.getMinValue()), 
StandardCharsets.UTF_8)).compareTo(max) > 0
+            || (new 
${filter.dataType}(String.valueOf(statistics.getMaxValue()), 
StandardCharsets.UTF_8)).compareTo(min) < 0;
+      }
+        <#else>
+      return false;
+        </#if>
       <#else>
       if(statistics.isEmpty()){
         return false;
@@ -994,8 +1286,14 @@ public final class ${className} {
 
     @Override
     public boolean valueSatisfy(Object value){
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary" || 
filter.javaBoxName == "String">
+      <#if filter.dataType == "boolean" || filter.javaBoxName == "String">
       return candidates.contains((${filter.dataType}) value);
+      <#elseif filter.dataType == "Binary">
+      if(value instanceof Binary){
+        return candidates.contains((${filter.dataType}) value);
+      } else {
+        return candidates.contains(new 
${filter.dataType}(String.valueOf(value), StandardCharsets.UTF_8));
+      }
       <#else>
       return candidates.contains(((Number) value).${filter.dataType}Value());
       </#if>
@@ -1142,8 +1440,14 @@ public final class ${className} {
 
     @Override
     public boolean valueSatisfy(Object value){
-      <#if filter.dataType == "boolean" || filter.dataType == "Binary" || 
filter.javaBoxName == "String">
+      <#if filter.dataType == "boolean" || filter.javaBoxName == "String">
       return !candidates.contains((${filter.dataType}) value);
+      <#elseif filter.dataType == "Binary">
+      if(value instanceof Binary){
+        return !candidates.contains((${filter.dataType}) value);
+      } else {
+        return !candidates.contains(new 
${filter.dataType}(String.valueOf(value), StandardCharsets.UTF_8));
+      }
       <#else>
       return !candidates.contains(((Number) value).${filter.dataType}Value());
       </#if>
diff --git 
a/java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/Statistics.java
 
b/java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/Statistics.java
index ee41b063..b1c2c463 100644
--- 
a/java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/Statistics.java
+++ 
b/java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/Statistics.java
@@ -24,6 +24,7 @@ import 
org.apache.tsfile.exception.filter.StatisticsClassException;
 import org.apache.tsfile.exception.write.UnknownColumnTypeException;
 import org.apache.tsfile.read.filter.basic.Filter;
 import org.apache.tsfile.utils.Binary;
+import org.apache.tsfile.utils.Pair;
 import org.apache.tsfile.utils.ReadWriteForEncodingUtils;
 import org.apache.tsfile.utils.ReadWriteIOUtils;
 
@@ -35,7 +36,9 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Serializable;
 import java.nio.ByteBuffer;
+import java.util.HashSet;
 import java.util.Objects;
+import java.util.Set;
 
 /**
  * This class is used for recording statistic information of each measurement 
in a delta file. While
@@ -63,6 +66,35 @@ public abstract class Statistics<T extends Serializable> {
 
   static final String STATS_UNSUPPORTED_MSG = "%s statistics does not support: 
%s";
 
+  private static final Set<Pair<TSDataType, TSDataType>> CAN_NOT_MERGE_PAIRS;
+
+  static {
+    CAN_NOT_MERGE_PAIRS = new HashSet<>();
+
+    // related pair about STRING
+    addSymmetricPairs(CAN_NOT_MERGE_PAIRS, TSDataType.INT32, 
TSDataType.STRING);
+    addSymmetricPairs(CAN_NOT_MERGE_PAIRS, TSDataType.INT64, 
TSDataType.STRING);
+    addSymmetricPairs(CAN_NOT_MERGE_PAIRS, TSDataType.FLOAT, 
TSDataType.STRING);
+    addSymmetricPairs(CAN_NOT_MERGE_PAIRS, TSDataType.DOUBLE, 
TSDataType.STRING);
+    addSymmetricPairs(CAN_NOT_MERGE_PAIRS, TSDataType.BOOLEAN, 
TSDataType.STRING);
+    addSymmetricPairs(CAN_NOT_MERGE_PAIRS, TSDataType.TIMESTAMP, 
TSDataType.STRING);
+    addSymmetricPairs(CAN_NOT_MERGE_PAIRS, TSDataType.DATE, TSDataType.STRING);
+    addSymmetricPairs(CAN_NOT_MERGE_PAIRS, TSDataType.BLOB, TSDataType.STRING);
+
+    // related pair about TEXT
+    addSymmetricPairs(CAN_NOT_MERGE_PAIRS, TSDataType.INT32, TSDataType.TEXT);
+    addSymmetricPairs(CAN_NOT_MERGE_PAIRS, TSDataType.INT64, TSDataType.TEXT);
+    addSymmetricPairs(CAN_NOT_MERGE_PAIRS, TSDataType.FLOAT, TSDataType.TEXT);
+    addSymmetricPairs(CAN_NOT_MERGE_PAIRS, TSDataType.DOUBLE, TSDataType.TEXT);
+    addSymmetricPairs(CAN_NOT_MERGE_PAIRS, TSDataType.BOOLEAN, 
TSDataType.TEXT);
+    addSymmetricPairs(CAN_NOT_MERGE_PAIRS, TSDataType.TIMESTAMP, 
TSDataType.TEXT);
+    addSymmetricPairs(CAN_NOT_MERGE_PAIRS, TSDataType.DATE, TSDataType.TEXT);
+    addSymmetricPairs(CAN_NOT_MERGE_PAIRS, TSDataType.BLOB, TSDataType.TEXT);
+
+    // related pari about TEXT and STRING
+    addSymmetricPairs(CAN_NOT_MERGE_PAIRS, TSDataType.TEXT, TSDataType.STRING);
+  }
+
   /**
    * static method providing statistic instance for respective data type.
    *
@@ -229,7 +261,24 @@ public abstract class Statistics<T extends Serializable> {
     return to.isCompatible(from)
         &&
         // cannot alter from TEXT to STRING because we cannot add statistic to 
the existing chunks
-        !(from == TSDataType.TEXT && to == TSDataType.STRING);
+        isSatisfyMerge(from, to);
+  }
+
+  private static void addSymmetricPairs(
+      Set<Pair<TSDataType, TSDataType>> set, TSDataType... dataTypes) {
+    for (int i = 0; i < dataTypes.length; i++) {
+      for (int j = i + 1; j < dataTypes.length; j++) {
+        set.add(new Pair<>(dataTypes[i], dataTypes[j]));
+        set.add(new Pair<>(dataTypes[j], dataTypes[i]));
+      }
+    }
+  }
+
+  public static boolean isSatisfyMerge(TSDataType from, TSDataType to) {
+    if (from == to) {
+      return true;
+    }
+    return !CAN_NOT_MERGE_PAIRS.contains(new Pair<>(from, to));
   }
 
   public void update(long time, boolean value) {
diff --git 
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/BinaryColumnBuilder.java
 
b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/BinaryColumnBuilder.java
index be952eaa..d6facd48 100644
--- 
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/BinaryColumnBuilder.java
+++ 
b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/BinaryColumnBuilder.java
@@ -28,6 +28,7 @@ import org.apache.tsfile.utils.RamUsageEstimator;
 import org.apache.tsfile.utils.TsPrimitiveType;
 import org.apache.tsfile.write.UnSupportedDataTypeException;
 
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 
 import static java.lang.Math.max;
@@ -100,6 +101,35 @@ public class BinaryColumnBuilder implements ColumnBuilder {
     return writeBinary(column.getBinary(index));
   }
 
+  @Override
+  public ColumnBuilder writeBoolean(boolean value) {
+    return writeBinary(new Binary(String.valueOf(value), 
StandardCharsets.UTF_8));
+  }
+
+  @Override
+  public ColumnBuilder writeInt(int value) {
+    return writeBinary(new Binary(String.valueOf(value), 
StandardCharsets.UTF_8));
+  }
+
+  @Override
+  public ColumnBuilder writeLong(long value) {
+    return writeBinary(new Binary(String.valueOf(value), 
StandardCharsets.UTF_8));
+  }
+
+  @Override
+  public ColumnBuilder writeFloat(float value) {
+    return writeBinary(new Binary(String.valueOf(value), 
StandardCharsets.UTF_8));
+  }
+
+  @Override
+  public ColumnBuilder writeDouble(double value) {
+    return writeBinary(new Binary(String.valueOf(value), 
StandardCharsets.UTF_8));
+  }
+
+  public ColumnBuilder writeDate(int value) {
+    return writeBinary(new Binary(TSDataType.getDateStringValue(value), 
StandardCharsets.UTF_8));
+  }
+
   @Override
   public ColumnBuilder writeTsPrimitiveType(TsPrimitiveType value) {
     return writeBinary(value.getBinary());
diff --git 
a/java/tsfile/src/main/java/org/apache/tsfile/read/reader/IPageReader.java 
b/java/tsfile/src/main/java/org/apache/tsfile/read/reader/IPageReader.java
index 9d6980be..1b870f86 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/reader/IPageReader.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/reader/IPageReader.java
@@ -43,6 +43,8 @@ public interface IPageReader extends IMetadata {
 
   boolean isModified();
 
+  void setModified(boolean modified);
+
   void initTsBlockBuilder(List<TSDataType> dataTypes);
 
   void setLimitOffset(PaginationController paginationController);
diff --git 
a/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/AbstractAlignedPageReader.java
 
b/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/AbstractAlignedPageReader.java
index 9230d486..ad5af3b5 100644
--- 
a/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/AbstractAlignedPageReader.java
+++ 
b/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/AbstractAlignedPageReader.java
@@ -348,6 +348,11 @@ public abstract class AbstractAlignedPageReader implements 
IPageReader {
     return isModified;
   }
 
+  @Override
+  public void setModified(boolean modified) {
+    this.isModified = modified;
+  }
+
   @Override
   public void initTsBlockBuilder(List<TSDataType> dataTypes) {
     if (paginationController.hasLimit()) {
diff --git 
a/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/PageReader.java 
b/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/PageReader.java
index ee74f815..7ba234cf 100644
--- 
a/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/PageReader.java
+++ 
b/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/PageReader.java
@@ -413,6 +413,11 @@ public class PageReader implements IPageReader {
     return pageHeader.isModified();
   }
 
+  @Override
+  public void setModified(boolean modified) {
+    pageHeader.setModified(modified);
+  }
+
   @Override
   public void initTsBlockBuilder(List<TSDataType> dataTypes) {
     // do nothing
diff --git 
a/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/ValuePageReader.java
 
b/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/ValuePageReader.java
index fc9dd375..998b2117 100644
--- 
a/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/ValuePageReader.java
+++ 
b/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/ValuePageReader.java
@@ -27,6 +27,7 @@ import org.apache.tsfile.file.metadata.statistics.Statistics;
 import org.apache.tsfile.read.common.BatchData;
 import org.apache.tsfile.read.common.BatchDataFactory;
 import org.apache.tsfile.read.common.TimeRange;
+import org.apache.tsfile.read.common.block.column.BinaryColumnBuilder;
 import org.apache.tsfile.read.filter.basic.Filter;
 import org.apache.tsfile.utils.Binary;
 import org.apache.tsfile.utils.ReadWriteIOUtils;
@@ -318,7 +319,6 @@ public class ValuePageReader {
           }
           break;
         case INT32:
-        case DATE:
           int anInt = valueDecoder.readInt(valueBuffer);
           if (keepCurrentRow[i]) {
             if (isDeleted[i]) {
@@ -328,6 +328,20 @@ public class ValuePageReader {
             }
           }
           break;
+        case DATE:
+          int anDate = valueDecoder.readInt(valueBuffer);
+          if (keepCurrentRow[i]) {
+            if (isDeleted[i]) {
+              columnBuilder.appendNull();
+            } else {
+              if (columnBuilder instanceof BinaryColumnBuilder) {
+                ((BinaryColumnBuilder) columnBuilder).writeDate(anDate);
+              } else {
+                columnBuilder.writeInt(anDate);
+              }
+            }
+          }
+          break;
         case INT64:
         case TIMESTAMP:
           long aLong = valueDecoder.readLong(valueBuffer);
@@ -403,12 +417,21 @@ public class ValuePageReader {
           }
           break;
         case INT32:
-        case DATE:
           int anInt = valueDecoder.readInt(valueBuffer);
           if (keepCurrentRow[i]) {
             columnBuilder.writeInt(anInt);
           }
           break;
+        case DATE:
+          int anDate = valueDecoder.readInt(valueBuffer);
+          if (keepCurrentRow[i]) {
+            if (columnBuilder instanceof BinaryColumnBuilder) {
+              ((BinaryColumnBuilder) columnBuilder).writeDate(anDate);
+            } else {
+              columnBuilder.writeInt(anDate);
+            }
+          }
+          break;
         case INT64:
         case TIMESTAMP:
           long aLong = valueDecoder.readLong(valueBuffer);
@@ -485,7 +508,15 @@ public class ValuePageReader {
             continue;
           }
           int aInt = valueDecoder.readInt(valueBuffer);
-          columnBuilder.writeInt(aInt);
+          if (dataType == TSDataType.INT32) {
+            columnBuilder.writeInt(aInt);
+          } else {
+            if (columnBuilder instanceof BinaryColumnBuilder) {
+              ((BinaryColumnBuilder) columnBuilder).writeDate(aInt);
+            } else {
+              columnBuilder.writeInt(aInt);
+            }
+          }
         }
         break;
       case INT64:
@@ -584,6 +615,10 @@ public class ValuePageReader {
     return pageHeader.isModified();
   }
 
+  public void setModified(boolean modified) {
+    pageHeader.setModified(modified);
+  }
+
   public boolean isDeleted(long timestamp) {
     while (deleteIntervalList != null && deleteCursor < 
deleteIntervalList.size()) {
       if (deleteIntervalList.get(deleteCursor).contains(timestamp)) {
diff --git 
a/java/tsfile/src/test/java/org/apache/tsfile/utils/TypeCastTest.java 
b/java/tsfile/src/test/java/org/apache/tsfile/utils/TypeCastTest.java
index 10d26db1..4d1d0006 100644
--- a/java/tsfile/src/test/java/org/apache/tsfile/utils/TypeCastTest.java
+++ b/java/tsfile/src/test/java/org/apache/tsfile/utils/TypeCastTest.java
@@ -24,6 +24,7 @@ import org.apache.tsfile.enums.TSDataType;
 import org.junit.Test;
 
 import java.nio.charset.StandardCharsets;
+import java.time.LocalDate;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
@@ -46,7 +47,21 @@ public class TypeCastTest {
       for (TSDataType to : dataTypes) {
         Object src = genValue(from);
         if (to.isCompatible(from)) {
-          assertEquals(genValue(to), to.castFromSingleValue(from, src));
+          if (to == TSDataType.STRING || to == TSDataType.TEXT) {
+            if (from == TSDataType.DATE) {
+              assertEquals(
+                  new Binary(LocalDate.ofEpochDay((int) src).toString(), 
StandardCharsets.UTF_8),
+                  new Binary(
+                      
LocalDate.ofEpochDay(Long.parseLong(genValue(to).toString())).toString(),
+                      StandardCharsets.UTF_8));
+            } else {
+              assertEquals(
+                  new Binary(src.toString(), StandardCharsets.UTF_8),
+                  to.castFromSingleValue(from, src));
+            }
+          } else {
+            assertEquals(genValue(to), to.castFromSingleValue(from, src));
+          }
         } else {
           assertThrows(ClassCastException.class, () -> 
to.castFromSingleValue(from, src));
         }
@@ -66,7 +81,7 @@ public class TypeCastTest {
         Object array = genValueArray(from);
         if (!to.isCompatible(from)) {
           assertThrows(ClassCastException.class, () -> to.castFromArray(from, 
array));
-          return;
+          continue;
         }
         switch (to) {
           case INT32:
@@ -84,8 +99,66 @@ public class TypeCastTest {
           case STRING:
           case BLOB:
           case TEXT:
-            assertArrayEquals(
-                (Binary[]) genValueArray(to), (Binary[]) 
to.castFromArray(from, array));
+            switch (from) {
+              case BLOB:
+              case STRING:
+                assertArrayEquals((Binary[]) array, (Binary[]) 
to.castFromArray(from, array));
+                break;
+              case INT32:
+                int[] tmpInt = (int[]) array;
+                Binary[] intResult = new Binary[tmpInt.length];
+                for (int i = 0; i < tmpInt.length; i++) {
+                  intResult[i] = new Binary(String.valueOf(tmpInt[i]), 
StandardCharsets.UTF_8);
+                }
+                assertArrayEquals(intResult, (Binary[]) to.castFromArray(from, 
array));
+                break;
+              case DATE:
+                int[] tmpDate = (int[]) array;
+                Binary[] dateResult = new Binary[tmpDate.length];
+                for (int i = 0; i < tmpDate.length; i++) {
+                  dateResult[i] =
+                      new Binary(TSDataType.getDateStringValue(tmpDate[i]), 
StandardCharsets.UTF_8);
+                }
+                assertArrayEquals(dateResult, (Binary[]) 
to.castFromArray(from, array));
+                break;
+              case INT64:
+              case TIMESTAMP:
+                long[] tmpLong = (long[]) array;
+                Binary[] longResult = new Binary[tmpLong.length];
+                for (int i = 0; i < tmpLong.length; i++) {
+                  longResult[i] = new Binary(String.valueOf(tmpLong[i]), 
StandardCharsets.UTF_8);
+                }
+                assertArrayEquals(longResult, (Binary[]) 
to.castFromArray(from, array));
+                break;
+              case FLOAT:
+                float[] tmpFloat = (float[]) array;
+                Binary[] floatResult = new Binary[tmpFloat.length];
+                for (int i = 0; i < tmpFloat.length; i++) {
+                  floatResult[i] = new Binary(String.valueOf(tmpFloat[i]), 
StandardCharsets.UTF_8);
+                }
+                assertArrayEquals(floatResult, (Binary[]) 
to.castFromArray(from, array));
+                break;
+              case DOUBLE:
+                double[] tmpDouble = (double[]) array;
+                Binary[] doubleResult = new Binary[tmpDouble.length];
+                for (int i = 0; i < tmpDouble.length; i++) {
+                  doubleResult[i] =
+                      new Binary(String.valueOf(tmpDouble[i]), 
StandardCharsets.UTF_8);
+                }
+                assertArrayEquals(doubleResult, (Binary[]) 
to.castFromArray(from, array));
+                break;
+              case BOOLEAN:
+                boolean[] tmpBoolean = (boolean[]) array;
+                Binary[] booleanResult = new Binary[tmpBoolean.length];
+                for (int i = 0; i < tmpBoolean.length; i++) {
+                  booleanResult[i] =
+                      new Binary(String.valueOf(tmpBoolean[i]), 
StandardCharsets.UTF_8);
+                }
+                assertArrayEquals(booleanResult, (Binary[]) 
to.castFromArray(from, array));
+                break;
+              default:
+                break;
+            }
             break;
           case FLOAT:
             assertArrayEquals(

Reply via email to