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

jackietien pushed a commit to branch IOTDB-6243
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 666c045fa885e39fff1650063dc95e7d28bf9845
Author: JackieTien97 <[email protected]>
AuthorDate: Thu Nov 9 14:55:44 2023 +0800

    tmp
---
 .../org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4   |  2 +-
 .../src/main/codegen/templates/constantFill.ftl    |  2 +-
 .../src/main/codegen/templates/previousFill.ftl    | 56 +++++++++++++---------
 .../execution/operator/process/fill/IFill.java     |  3 +-
 .../process/fill/{IFill.java => IFillFilter.java}  | 12 +++--
 .../FixedIntervalFillFilter.java}                  | 19 +++++---
 .../MonthIntervalFillFilter.java}                  | 24 +++++++---
 .../process/fill/identity/IdentityFill.java        |  3 +-
 .../queryengine/plan/analyze/AnalyzeVisitor.java   |  2 +-
 .../db/queryengine/plan/parser/ASTVisitor.java     |  7 +++
 .../plan/planner/OperatorTreeGenerator.java        | 28 +++++++----
 .../plan/planner/plan/node/PlanGraphPrinter.java   |  3 ++
 .../planner/plan/parameter/FillDescriptor.java     | 35 ++++++++++----
 .../plan/statement/component/FillComponent.java    | 14 ++++++
 .../iotdb/db/utils/TimestampPrecisionUtils.java    |  2 +-
 .../plan/optimization/TestPlanBuilder.java         |  4 +-
 .../plan/plan/node/process/FillNodeSerdeTest.java  |  2 +-
 .../apache/iotdb/tsfile/utils/TimeDuration.java    |  8 ++++
 18 files changed, 163 insertions(+), 63 deletions(-)

diff --git 
a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 
b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
index b2224e51eb7..52be8d99310 100644
--- 
a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
+++ 
b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
@@ -725,7 +725,7 @@ sortKey
 
 // ---- Fill Clause
 fillClause
-    : FILL LR_BRACKET (LINEAR | PREVIOUS | constant) RR_BRACKET
+    : FILL LR_BRACKET (LINEAR | PREVIOUS | constant (COMMA 
interval=DURATION_LITERAL)?) RR_BRACKET
     ;
 
 // ---- Pagination Clause
diff --git a/iotdb-core/datanode/src/main/codegen/templates/constantFill.ftl 
b/iotdb-core/datanode/src/main/codegen/templates/constantFill.ftl
index 7ded1f9a3aa..e564fcfabba 100644
--- a/iotdb-core/datanode/src/main/codegen/templates/constantFill.ftl
+++ b/iotdb-core/datanode/src/main/codegen/templates/constantFill.ftl
@@ -50,7 +50,7 @@ public class ${className} implements IFill {
   }
 
   @Override
-  public Column fill(Column valueColumn) {
+  public Column fill(TimeColumn timeColumn, Column valueColumn) {
     int size = valueColumn.getPositionCount();
     // if this valueColumn doesn't have any null value, or it's empty, just 
return itself;
     if (!valueColumn.mayHaveNull() || size == 0) {
diff --git a/iotdb-core/datanode/src/main/codegen/templates/previousFill.ftl 
b/iotdb-core/datanode/src/main/codegen/templates/previousFill.ftl
index 8006ed70982..b8fc0d5b05e 100644
--- a/iotdb-core/datanode/src/main/codegen/templates/previousFill.ftl
+++ b/iotdb-core/datanode/src/main/codegen/templates/previousFill.ftl
@@ -25,10 +25,12 @@
 package 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.previous;
 
 import org.apache.iotdb.db.queryengine.execution.operator.process.fill.IFill;
+import 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.IFillFilter;
 import org.apache.iotdb.tsfile.access.Column;
 import org.apache.iotdb.tsfile.read.common.block.column.${type.column};
 import org.apache.iotdb.tsfile.read.common.block.column.${type.column}Builder;
 import org.apache.iotdb.tsfile.read.common.block.column.RunLengthEncodedColumn;
+import org.apache.iotdb.tsfile.read.common.block.column.TimeColumn;
 <#if type.dataType == "Binary">
   import org.apache.iotdb.tsfile.utils.Binary;
 </#if>
@@ -43,11 +45,19 @@ public class ${className} implements IFill {
 
   // previous value
   private ${type.dataType} value;
+  // previous time
+  private long previousTime;
   // whether previous value is null
   private boolean previousIsNull = true;
 
+  private final IFillFilter filter;
+
+  public ${className}(IFillFilter filter) {
+    this.filter = filter;
+  }
+
   @Override
-  public Column fill(Column valueColumn) {
+  public Column fill(TimeColumn timeColumn, Column valueColumn) {
     int size = valueColumn.getPositionCount();
     // if this valueColumn is empty, just return itself;
     if (size == 0) {
@@ -58,6 +68,7 @@ public class ${className} implements IFill {
     if (!valueColumn.mayHaveNull()) {
       previousIsNull = false;
       // update the value using last non-null value
+      previousTime = timeColumn.getLong(size - 1);
       value = valueColumn.get${type.dataType?cap_first}(size - 1);
       return valueColumn;
     }
@@ -65,35 +76,36 @@ public class ${className} implements IFill {
     if (valueColumn instanceof RunLengthEncodedColumn) {
       if (previousIsNull) {
         return new 
RunLengthEncodedColumn(${type.column}Builder.NULL_VALUE_BLOCK, size);
-      } else {
+      } else if (filter.needFill(timeColumn.getLong(size - 1), previousTime)) {
         return new RunLengthEncodedColumn(
             new ${type.column}(1, Optional.empty(), new ${type.dataType}[] 
{value}), size);
       }
-    } else {
-      ${type.dataType}[] array = new ${type.dataType}[size];
-      boolean[] isNull = new boolean[size];
-      // have null value
-      boolean hasNullValue = false;
-      for (int i = 0; i < size; i++) {
-        if (valueColumn.isNull(i)) {
-          if (previousIsNull) {
-            isNull[i] = true;
-            hasNullValue = true;
-          } else {
-            array[i] = value;
-          }
+    }
+
+    ${type.dataType}[] array = new ${type.dataType}[size];
+    boolean[] isNull = new boolean[size];
+    // have null value
+    boolean hasNullValue = false;
+    for (int i = 0; i < size; i++) {
+      if (valueColumn.isNull(i)) {
+        if (previousIsNull || !filter.needFill(timeColumn.getLong(i), 
previousTime)) {
+          isNull[i] = true;
+          hasNullValue = true;
         } else {
-          array[i] = valueColumn.get${type.dataType?cap_first}(i);
-          value = array[i];
-          previousIsNull = false;
+          array[i] = value;
         }
-      }
-      if (hasNullValue) {
-        return new ${type.column}(size, Optional.of(isNull), array);
       } else {
-        return new ${type.column}(size, Optional.empty(), array);
+        array[i] = valueColumn.get${type.dataType?cap_first}(i);
+        previousTime = timeColumn.getLong(i);
+        value = array[i];
+        previousIsNull = false;
       }
     }
+    if (hasNullValue) {
+      return new ${type.column}(size, Optional.of(isNull), array);
+    } else {
+      return new ${type.column}(size, Optional.empty(), array);
+    }
   }
 }
 </#list>
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/IFill.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/IFill.java
index c6e9bf5683c..6a20e63d4d8 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/IFill.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/IFill.java
@@ -20,8 +20,9 @@
 package org.apache.iotdb.db.queryengine.execution.operator.process.fill;
 
 import org.apache.iotdb.tsfile.access.Column;
+import org.apache.iotdb.tsfile.read.common.block.column.TimeColumn;
 
 public interface IFill {
 
-  Column fill(Column valueColumn);
+  Column fill(TimeColumn timeColumn, Column valueColumn);
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/IFill.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/IFillFilter.java
similarity index 74%
copy from 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/IFill.java
copy to 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/IFillFilter.java
index c6e9bf5683c..c0ee791baef 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/IFill.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/IFillFilter.java
@@ -19,9 +19,15 @@
 
 package org.apache.iotdb.db.queryengine.execution.operator.process.fill;
 
-import org.apache.iotdb.tsfile.access.Column;
+public interface IFillFilter {
 
-public interface IFill {
+  // always fill
+  IFillFilter TRUE = (time, previousTime) -> true;
 
-  Column fill(Column valueColumn);
+  /**
+   * @param time current timestamp
+   * @param previousTime previous timestamp
+   * @return true if we can fill, otherwise we keep null
+   */
+  boolean needFill(long time, long previousTime);
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/identity/IdentityFill.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/filter/FixedIntervalFillFilter.java
similarity index 62%
copy from 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/identity/IdentityFill.java
copy to 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/filter/FixedIntervalFillFilter.java
index 9c9bcbcd93e..7b1fdd09550 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/identity/IdentityFill.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/filter/FixedIntervalFillFilter.java
@@ -17,15 +17,22 @@
  * under the License.
  */
 
-package 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.identity;
+package org.apache.iotdb.db.queryengine.execution.operator.process.fill.filter;
 
-import org.apache.iotdb.db.queryengine.execution.operator.process.fill.IFill;
-import org.apache.iotdb.tsfile.access.Column;
+import 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.IFillFilter;
 
-public class IdentityFill implements IFill {
+public class FixedIntervalFillFilter implements IFillFilter {
+
+  // the time precision of this field is same as the system time_precision 
configuration.
+  private final long timeInterval;
+
+  public FixedIntervalFillFilter(long timeInterval) {
+    this.timeInterval = timeInterval;
+  }
 
   @Override
-  public Column fill(Column valueColumn) {
-    return valueColumn;
+  public boolean needFill(long time, long previousTime) {
+    // the reason that we use Math.abs is that we may use order by time desc 
which will cause previousTime is larger than time
+    return Math.abs(time - previousTime) <= timeInterval;
   }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/identity/IdentityFill.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/filter/MonthIntervalFillFilter.java
similarity index 60%
copy from 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/identity/IdentityFill.java
copy to 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/filter/MonthIntervalFillFilter.java
index 9c9bcbcd93e..1f3c193833b 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/identity/IdentityFill.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/filter/MonthIntervalFillFilter.java
@@ -17,15 +17,27 @@
  * under the License.
  */
 
-package 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.identity;
+package org.apache.iotdb.db.queryengine.execution.operator.process.fill.filter;
 
-import org.apache.iotdb.db.queryengine.execution.operator.process.fill.IFill;
-import org.apache.iotdb.tsfile.access.Column;
+import 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.IFillFilter;
 
-public class IdentityFill implements IFill {
+public class MonthIntervalFillFilter implements IFillFilter {
+
+  // month part of time duration
+  public final int monthDuration;
+  // non-month part of time duration, its precision is same as current 
time_precision
+  public final long nonMonthDuration;
+
+  public MonthIntervalFillFilter(int monthDuration, long nonMonthDuration) {
+    this.monthDuration = monthDuration;
+    this.nonMonthDuration = nonMonthDuration;
+  }
 
   @Override
-  public Column fill(Column valueColumn) {
-    return valueColumn;
+  public boolean needFill(long time, long previousTime) {
+    long smaller = Math.min(time, previousTime);
+    long greater = Math.max(time, previousTime);
+
+    return false;
   }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/identity/IdentityFill.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/identity/IdentityFill.java
index 9c9bcbcd93e..ac4dc322a9d 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/identity/IdentityFill.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/fill/identity/IdentityFill.java
@@ -21,11 +21,12 @@ package 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.identity
 
 import org.apache.iotdb.db.queryengine.execution.operator.process.fill.IFill;
 import org.apache.iotdb.tsfile.access.Column;
+import org.apache.iotdb.tsfile.read.common.block.column.TimeColumn;
 
 public class IdentityFill implements IFill {
 
   @Override
-  public Column fill(Column valueColumn) {
+  public Column fill(TimeColumn timeColumn, Column valueColumn) {
     return valueColumn;
   }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
index 96e8c9f5a42..3b18c01ce0f 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
@@ -1782,7 +1782,7 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
 
     FillComponent fillComponent = queryStatement.getFillComponent();
     analysis.setFillDescriptor(
-        new FillDescriptor(fillComponent.getFillPolicy(), 
fillComponent.getFillValue()));
+        new FillDescriptor(fillComponent.getFillPolicy(), 
fillComponent.getFillValue(), fillComponent.getTimeDurationThreshold()));
   }
 
   private void analyzeDataPartition(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
index 4750d5e60af..93cef11658d 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
@@ -1667,6 +1667,7 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
       fillComponent.setFillPolicy(FillPolicy.LINEAR);
     } else if (ctx.PREVIOUS() != null) {
       fillComponent.setFillPolicy(FillPolicy.PREVIOUS);
+
     } else if (ctx.constant() != null) {
       fillComponent.setFillPolicy(FillPolicy.VALUE);
       Literal fillValue = parseLiteral(ctx.constant());
@@ -1674,6 +1675,12 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
     } else {
       throw new SemanticException("Unknown FILL type.");
     }
+    if (ctx.interval != null) {
+      if (fillComponent.getFillPolicy() != FillPolicy.PREVIOUS) {
+        throw new SemanticException("Only FILL(PREVIOUS) support specifying 
the time duration threshold.");
+      }
+      
fillComponent.setTimeDurationThreshold(DateTimeUtils.constructTimeDuration(ctx.interval.getText()));
+    }
     return fillComponent;
   }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java
index 0f99f170725..26a11276993 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java
@@ -64,6 +64,7 @@ import 
org.apache.iotdb.db.queryengine.execution.operator.process.TagAggregation
 import org.apache.iotdb.db.queryengine.execution.operator.process.TopKOperator;
 import 
org.apache.iotdb.db.queryengine.execution.operator.process.TransformOperator;
 import org.apache.iotdb.db.queryengine.execution.operator.process.fill.IFill;
+import 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.IFillFilter;
 import 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.ILinearFill;
 import 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.constant.BinaryConstantFill;
 import 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.constant.BooleanConstantFill;
@@ -71,6 +72,7 @@ import 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.constant.
 import 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.constant.FloatConstantFill;
 import 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.constant.IntConstantFill;
 import 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.constant.LongConstantFill;
+import 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.filter.FixedIntervalFillFilter;
 import 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.identity.IdentityFill;
 import 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.identity.IdentityLinearFill;
 import 
org.apache.iotdb.db.queryengine.execution.operator.process.fill.linear.DoubleLinearFill;
@@ -227,6 +229,7 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.Validate;
+import org.apache.iotdb.tsfile.utils.TimeDuration;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -934,7 +937,7 @@ public class OperatorTreeGenerator extends 
PlanVisitor<Operator, LocalExecutionP
       case PREVIOUS:
         context.getTimeSliceAllocator().recordExecutionWeight(operatorContext, 
1);
         return new FillOperator(
-            operatorContext, getPreviousFill(inputColumns, inputDataTypes), 
child);
+            operatorContext, getPreviousFill(inputColumns, inputDataTypes, 
descriptor.getTimeDurationThreshold()), child);
       case LINEAR:
         context.getTimeSliceAllocator().recordExecutionWeight(operatorContext, 
1);
         return new LinearFillOperator(
@@ -978,27 +981,36 @@ public class OperatorTreeGenerator extends 
PlanVisitor<Operator, LocalExecutionP
     return constantFill;
   }
 
-  private IFill[] getPreviousFill(int inputColumns, List<TSDataType> 
inputDataTypes) {
+  private IFill[] getPreviousFill(int inputColumns, List<TSDataType> 
inputDataTypes, TimeDuration timeDurationThreshold) {
+    IFillFilter filter;
+    if (timeDurationThreshold == null) {
+      filter = IFillFilter.TRUE;
+    } else if (!timeDurationThreshold.containsMonth()) {
+      filter = new 
FixedIntervalFillFilter(timeDurationThreshold.nonMonthDuration);
+    } else {
+
+    }
+
     IFill[] previousFill = new IFill[inputColumns];
     for (int i = 0; i < inputColumns; i++) {
       switch (inputDataTypes.get(i)) {
         case BOOLEAN:
-          previousFill[i] = new BooleanPreviousFill();
+          previousFill[i] = new BooleanPreviousFill(filter);
           break;
         case TEXT:
-          previousFill[i] = new BinaryPreviousFill();
+          previousFill[i] = new BinaryPreviousFill(filter);
           break;
         case INT32:
-          previousFill[i] = new IntPreviousFill();
+          previousFill[i] = new IntPreviousFill(filter);
           break;
         case INT64:
-          previousFill[i] = new LongPreviousFill();
+          previousFill[i] = new LongPreviousFill(filter);
           break;
         case FLOAT:
-          previousFill[i] = new FloatPreviousFill();
+          previousFill[i] = new FloatPreviousFill(filter);
           break;
         case DOUBLE:
-          previousFill[i] = new DoublePreviousFill();
+          previousFill[i] = new DoublePreviousFill(filter);
           break;
         default:
           throw new IllegalArgumentException(UNKNOWN_DATATYPE + 
inputDataTypes.get(i));
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java
index 5ff7ffef463..7cdb51335ab 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java
@@ -215,6 +215,9 @@ public class PlanGraphPrinter extends 
PlanVisitor<List<String>, PlanGraphPrinter
     List<String> boxValue = new ArrayList<>();
     boxValue.add(String.format("Fill-%s", node.getPlanNodeId().getId()));
     boxValue.add(String.format("Policy: %s", 
node.getFillDescriptor().getFillPolicy()));
+    if (node.getFillDescriptor().getTimeDurationThreshold() != null) {
+      boxValue.add(String.format("TimeDurationThreshold: %s", 
node.getFillDescriptor().getTimeDurationThreshold()));
+    }
     return render(node, boxValue, context);
   }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/parameter/FillDescriptor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/parameter/FillDescriptor.java
index 410e20e157f..20d08c784d6 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/parameter/FillDescriptor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/parameter/FillDescriptor.java
@@ -22,6 +22,7 @@ package 
org.apache.iotdb.db.queryengine.plan.planner.plan.parameter;
 import org.apache.iotdb.db.queryengine.plan.statement.component.FillPolicy;
 import org.apache.iotdb.db.queryengine.plan.statement.literal.Literal;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+import org.apache.iotdb.tsfile.utils.TimeDuration;
 
 import java.io.DataOutputStream;
 import java.io.IOException;
@@ -34,15 +35,15 @@ public class FillDescriptor {
   private final FillPolicy fillPolicy;
 
   // filled value when fillPolicy is VALUE
-  private Literal fillValue;
+  private final Literal fillValue;
 
-  public FillDescriptor(FillPolicy fillPolicy) {
-    this.fillPolicy = fillPolicy;
-  }
+  // if
+  private final TimeDuration timeDurationThreshold;
 
-  public FillDescriptor(FillPolicy fillPolicy, Literal fillValue) {
+  public FillDescriptor(FillPolicy fillPolicy, Literal fillValue, TimeDuration 
timeDurationThreshold) {
     this.fillPolicy = fillPolicy;
     this.fillValue = fillValue;
+    this.timeDurationThreshold = timeDurationThreshold;
   }
 
   public void serialize(ByteBuffer byteBuffer) {
@@ -50,6 +51,10 @@ public class FillDescriptor {
     if (fillPolicy == FillPolicy.VALUE) {
       fillValue.serialize(byteBuffer);
     }
+    ReadWriteIOUtils.write(timeDurationThreshold != null, byteBuffer);
+    if (timeDurationThreshold != null) {
+      timeDurationThreshold.serialize(byteBuffer);
+    }
   }
 
   public void serialize(DataOutputStream stream) throws IOException {
@@ -57,16 +62,24 @@ public class FillDescriptor {
     if (fillPolicy == FillPolicy.VALUE) {
       fillValue.serialize(stream);
     }
+    ReadWriteIOUtils.write(timeDurationThreshold != null, stream);
+    if (timeDurationThreshold != null) {
+      timeDurationThreshold.serialize(stream);
+    }
   }
 
   public static FillDescriptor deserialize(ByteBuffer byteBuffer) {
     FillPolicy fillPolicy = 
FillPolicy.values()[ReadWriteIOUtils.readInt(byteBuffer)];
+    Literal fillValue = null;
     if (fillPolicy == FillPolicy.VALUE) {
-      Literal fillValue = Literal.deserialize(byteBuffer);
-      return new FillDescriptor(fillPolicy, fillValue);
-    } else {
-      return new FillDescriptor(fillPolicy);
+      fillValue = Literal.deserialize(byteBuffer);
     }
+    boolean hasTimeDurationThreshold = ReadWriteIOUtils.readBool(byteBuffer);
+    TimeDuration timeDurationThreshold = null;
+    if (hasTimeDurationThreshold) {
+      timeDurationThreshold = TimeDuration.deserialize(byteBuffer);
+    }
+    return new FillDescriptor(fillPolicy, fillValue, timeDurationThreshold);
   }
 
   public FillPolicy getFillPolicy() {
@@ -77,6 +90,10 @@ public class FillDescriptor {
     return fillValue;
   }
 
+  public TimeDuration getTimeDurationThreshold() {
+    return timeDurationThreshold;
+  }
+
   @Override
   public boolean equals(Object o) {
     if (this == o) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/component/FillComponent.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/component/FillComponent.java
index 3cedb366cf3..65c13a77d9e 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/component/FillComponent.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/component/FillComponent.java
@@ -21,6 +21,7 @@ package 
org.apache.iotdb.db.queryengine.plan.statement.component;
 
 import org.apache.iotdb.db.queryengine.plan.statement.StatementNode;
 import org.apache.iotdb.db.queryengine.plan.statement.literal.Literal;
+import org.apache.iotdb.tsfile.utils.TimeDuration;
 
 /** This class maintains information of {@code FILL} clause. */
 public class FillComponent extends StatementNode {
@@ -28,6 +29,8 @@ public class FillComponent extends StatementNode {
   private FillPolicy fillPolicy;
   private Literal fillValue;
 
+  private TimeDuration timeDurationThreshold;
+
   public FillComponent() {
     // do nothing
   }
@@ -48,6 +51,14 @@ public class FillComponent extends StatementNode {
     this.fillValue = fillValue;
   }
 
+  public TimeDuration getTimeDurationThreshold() {
+    return timeDurationThreshold;
+  }
+
+  public void setTimeDurationThreshold(TimeDuration timeDurationThreshold) {
+    this.timeDurationThreshold = timeDurationThreshold;
+  }
+
   public String toSQLString() {
     StringBuilder sqlBuilder = new StringBuilder();
     sqlBuilder.append("FILL(");
@@ -56,6 +67,9 @@ public class FillComponent extends StatementNode {
     } else {
       sqlBuilder.append(fillValue.toString());
     }
+    if (timeDurationThreshold != null) {
+      sqlBuilder.append(", ").append(timeDurationThreshold);
+    }
     sqlBuilder.append(')');
     return sqlBuilder.toString();
   }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/TimestampPrecisionUtils.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/TimestampPrecisionUtils.java
index e57f2e851c5..768d0030e96 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/TimestampPrecisionUtils.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/TimestampPrecisionUtils.java
@@ -24,7 +24,7 @@ import org.apache.iotdb.db.exception.sql.SemanticException;
 import java.util.concurrent.TimeUnit;
 
 public class TimestampPrecisionUtils {
-  static String TIMESTAMP_PRECISION =
+  public static String TIMESTAMP_PRECISION =
       CommonDescriptor.getInstance().getConfig().getTimestampPrecision();
   private static final boolean isTimestampPrecisionCheckEnabled =
       
CommonDescriptor.getInstance().getConfig().isTimestampPrecisionCheckEnabled();
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/optimization/TestPlanBuilder.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/optimization/TestPlanBuilder.java
index 734cae7d89f..36043c2b03d 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/optimization/TestPlanBuilder.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/optimization/TestPlanBuilder.java
@@ -128,7 +128,7 @@ public class TestPlanBuilder {
 
   public TestPlanBuilder fill(String id, FillPolicy fillPolicy) {
     this.root =
-        new FillNode(new PlanNodeId(id), getRoot(), new 
FillDescriptor(fillPolicy), Ordering.ASC);
+        new FillNode(new PlanNodeId(id), getRoot(), new 
FillDescriptor(fillPolicy, null, null), Ordering.ASC);
     return this;
   }
 
@@ -137,7 +137,7 @@ public class TestPlanBuilder {
         new FillNode(
             new PlanNodeId(id),
             getRoot(),
-            new FillDescriptor(FillPolicy.VALUE, new LongLiteral(intValue)),
+            new FillDescriptor(FillPolicy.VALUE, new LongLiteral(intValue), 
null),
             Ordering.ASC);
     return this;
   }
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/plan/node/process/FillNodeSerdeTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/plan/node/process/FillNodeSerdeTest.java
index 11c4e8de6ce..57457b7765d 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/plan/node/process/FillNodeSerdeTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/plan/node/process/FillNodeSerdeTest.java
@@ -43,7 +43,7 @@ public class FillNodeSerdeTest {
         new FillNode(
             new PlanNodeId("TestFillNode"),
             timeJoinNode,
-            new FillDescriptor(FillPolicy.VALUE, new LongLiteral("100")),
+            new FillDescriptor(FillPolicy.VALUE, new LongLiteral("100"), null),
             Ordering.ASC);
 
     ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
diff --git 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/utils/TimeDuration.java
 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/utils/TimeDuration.java
index 507a76f00cc..2ba4d4ca9d7 100644
--- 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/utils/TimeDuration.java
+++ 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/utils/TimeDuration.java
@@ -191,4 +191,12 @@ public class TimeDuration implements Serializable {
   public int hashCode() {
     return Objects.hash(monthDuration, nonMonthDuration);
   }
+
+  @Override
+  public String toString() {
+    return "TimeDuration{" +
+        (monthDuration > 0 ?  monthDuration + "mo, " : "") +
+        (nonMonthDuration > 0 ? nonMonthDuration : "")+
+        '}';
+  }
 }

Reply via email to