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 : "")+ + '}'; + } }
