You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ja...@apache.org on 2023/11/09 13:02:59 UTC
(iotdb) 01/02: tmp
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 <ja...@gmail.com>
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 : "")+
+ '}';
+ }
}