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 2021/11/07 09:24:45 UTC
[iotdb] branch master updated: [IOTDB-1760] Support other
aggregations in group by fill (#4303)
This is an automated email from the ASF dual-hosted git repository.
jackietien pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 959da45 [IOTDB-1760] Support other aggregations in group by fill (#4303)
959da45 is described below
commit 959da45cf54a4bc4ee91bb723222c5b1798432ac
Author: CRZbulabula <33...@users.noreply.github.com>
AuthorDate: Sun Nov 7 17:24:04 2021 +0800
[IOTDB-1760] Support other aggregations in group by fill (#4303)
---
.../org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 | 2 +-
.../cluster/query/fill/ClusterLinearFill.java | 8 +-
.../cluster/query/fill/ClusterPreviousFill.java | 2 +-
.../qp/logical/crud/GroupByFillQueryOperator.java | 13 -
.../apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java | 101 +-
.../dataset/groupby/GroupByEngineDataSet.java | 159 +-
.../query/dataset/groupby/GroupByFillDataSet.java | 220 ---
.../GroupByFillWithoutValueFilterDataSet.java | 577 +++++++
.../groupby/GroupByWithValueFilterDataSet.java | 2 +-
.../groupby/GroupByWithoutValueFilterDataSet.java | 4 +-
.../iotdb/db/query/executor/QueryRouter.java | 59 +-
.../apache/iotdb/db/query/executor/fill/IFill.java | 83 +-
.../iotdb/db/query/executor/fill/LinearFill.java | 81 +-
.../iotdb/db/query/executor/fill/PreviousFill.java | 40 +-
.../iotdb/db/query/executor/fill/ValueFill.java | 4 +-
.../iotdb/db/integration/IoTDBGroupByFillIT.java | 1785 +++++++++++++++++---
.../db/integration/IoTDBGroupByFillMixPathsIT.java | 294 ++++
.../db/integration/IoTDBGroupByMonthFillIT.java | 274 +++
.../iotdb/db/qp/physical/PhysicalPlanTest.java | 93 +-
.../dataset/groupby/GroupByFillDataSetTest.java | 170 +-
.../apache/iotdb/tsfile/read/common/RowRecord.java | 6 +-
21 files changed, 3221 insertions(+), 756 deletions(-)
diff --git a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
index 1140582..3324759 100644
--- a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
+++ b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
@@ -339,7 +339,7 @@ groupByTimeClause
;
groupByFillClause
- : GROUP BY LR_BRACKET timeInterval COMMA DURATION_LITERAL RR_BRACKET
+ : GROUP BY LR_BRACKET timeInterval COMMA DURATION_LITERAL (COMMA DURATION_LITERAL)? RR_BRACKET
FILL LR_BRACKET typeClause (COMMA typeClause)* RR_BRACKET
;
diff --git a/cluster/src/main/java/org/apache/iotdb/cluster/query/fill/ClusterLinearFill.java b/cluster/src/main/java/org/apache/iotdb/cluster/query/fill/ClusterLinearFill.java
index ed1cd7a..2264763 100644
--- a/cluster/src/main/java/org/apache/iotdb/cluster/query/fill/ClusterLinearFill.java
+++ b/cluster/src/main/java/org/apache/iotdb/cluster/query/fill/ClusterLinearFill.java
@@ -42,7 +42,8 @@ public class ClusterLinearFill extends LinearFill {
Arrays.asList(SQLConstant.MIN_TIME, SQLConstant.FIRST_VALUE);
ClusterLinearFill(LinearFill fill, MetaGroupMember metaGroupMember) {
- super(fill.getDataType(), fill.getQueryTime(), fill.getBeforeRange(), fill.getAfterRange());
+ super(
+ fill.getDataType(), fill.getQueryStartTime(), fill.getBeforeRange(), fill.getAfterRange());
this.metaGroupMember = metaGroupMember;
this.aggregator = new ClusterAggregator(metaGroupMember);
}
@@ -51,8 +52,9 @@ public class ClusterLinearFill extends LinearFill {
protected TimeValuePair calculatePrecedingPoint() {
// calculate the preceding point can be viewed as a previous fill
ClusterPreviousFill clusterPreviousFill =
- new ClusterPreviousFill(dataType, queryTime, beforeRange, metaGroupMember);
- clusterPreviousFill.configureFill(seriesPath, dataType, queryTime, deviceMeasurements, context);
+ new ClusterPreviousFill(dataType, queryStartTime, beforeRange, metaGroupMember);
+ clusterPreviousFill.configureFill(
+ seriesPath, dataType, queryStartTime, deviceMeasurements, context);
return clusterPreviousFill.getFillResult();
}
diff --git a/cluster/src/main/java/org/apache/iotdb/cluster/query/fill/ClusterPreviousFill.java b/cluster/src/main/java/org/apache/iotdb/cluster/query/fill/ClusterPreviousFill.java
index 548af4b..cd78770 100644
--- a/cluster/src/main/java/org/apache/iotdb/cluster/query/fill/ClusterPreviousFill.java
+++ b/cluster/src/main/java/org/apache/iotdb/cluster/query/fill/ClusterPreviousFill.java
@@ -61,7 +61,7 @@ public class ClusterPreviousFill extends PreviousFill {
private TimeValuePair fillResult;
ClusterPreviousFill(PreviousFill fill, MetaGroupMember metaGroupMember) {
- super(fill.getDataType(), fill.getQueryTime(), fill.getBeforeRange());
+ super(fill.getDataType(), fill.getQueryStartTime(), fill.getBeforeRange());
this.metaGroupMember = metaGroupMember;
}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/GroupByFillQueryOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/GroupByFillQueryOperator.java
index ac621cf..e849b07 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/GroupByFillQueryOperator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/GroupByFillQueryOperator.java
@@ -19,9 +19,7 @@
package org.apache.iotdb.db.qp.logical.crud;
-import org.apache.iotdb.db.exception.query.LogicalOperatorException;
import org.apache.iotdb.db.exception.query.QueryProcessException;
-import org.apache.iotdb.db.qp.constant.SQLConstant;
import org.apache.iotdb.db.qp.physical.PhysicalPlan;
import org.apache.iotdb.db.qp.physical.crud.AlignByDevicePlan;
import org.apache.iotdb.db.qp.physical.crud.GroupByTimeFillPlan;
@@ -31,17 +29,6 @@ import org.apache.iotdb.db.qp.strategy.PhysicalGenerator;
public class GroupByFillQueryOperator extends GroupByQueryOperator {
@Override
- public void check() throws LogicalOperatorException {
- super.check();
-
- for (String aggregation : selectComponent.getAggregationFunctions()) {
- if (!SQLConstant.LAST_VALUE.equals(aggregation)) {
- throw new LogicalOperatorException("Group By Fill only support last_value function");
- }
- }
- }
-
- @Override
public PhysicalPlan generatePhysicalPlan(PhysicalGenerator generator)
throws QueryProcessException {
return isAlignByDevice()
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java b/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
index 8fe80cb..09befa7 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
@@ -1108,25 +1108,32 @@ public class IoTDBSqlVisitor extends IoTDBSqlParserBaseVisitor<Operator> {
private void parseGroupByFillClause(IoTDBSqlParser.GroupByFillClauseContext ctx) {
GroupByFillClauseComponent groupByFillClauseComponent = new GroupByFillClauseComponent();
groupByFillClauseComponent.setLeftCRightO(ctx.timeInterval().LS_BRACKET() != null);
-
// parse timeUnit
groupByFillClauseComponent.setUnit(
- DatetimeUtils.convertDurationStrToLong(ctx.DURATION_LITERAL().getText()));
- groupByFillClauseComponent.setSlidingStep(groupByFillClauseComponent.getUnit());
+ parseTimeUnitOrSlidingStep(
+ ctx.DURATION_LITERAL(0).getText(), true, groupByFillClauseComponent));
+ // parse sliding step
+ if (ctx.DURATION_LITERAL().size() == 2) {
+ groupByFillClauseComponent.setSlidingStep(
+ parseTimeUnitOrSlidingStep(
+ ctx.DURATION_LITERAL(1).getText(), false, groupByFillClauseComponent));
+ if (groupByFillClauseComponent.getSlidingStep() < groupByFillClauseComponent.getUnit()) {
+ throw new SQLParserException(
+ "The third parameter sliding step shouldn't be smaller than the second parameter time interval.");
+ }
+ } else {
+ groupByFillClauseComponent.setSlidingStep(groupByFillClauseComponent.getUnit());
+ groupByFillClauseComponent.setSlidingStepByMonth(
+ groupByFillClauseComponent.isIntervalByMonth());
+ }
parseTimeInterval(ctx.timeInterval(), groupByFillClauseComponent);
List<IoTDBSqlParser.TypeClauseContext> list = ctx.typeClause();
Map<TSDataType, IFill> fillTypes = new EnumMap<>(TSDataType.class);
for (IoTDBSqlParser.TypeClauseContext typeClause : list) {
- // group by fill doesn't support linear fill
- if (typeClause.linearClause() != null) {
- throw new SQLParserException("group by fill doesn't support linear fill");
- }
- // all type use the same fill way
if (typeClause.ALL() != null) {
parseAllTypeClause(typeClause, fillTypes);
- break;
} else {
parsePrimitiveTypeClause(typeClause, fillTypes);
}
@@ -1207,27 +1214,43 @@ public class IoTDBSqlVisitor extends IoTDBSqlParserBaseVisitor<Operator> {
private void parseAllTypeClause(
IoTDBSqlParser.TypeClauseContext ctx, Map<TSDataType, IFill> fillTypes) {
IFill fill;
- long preRange;
- if (ctx.previousUntilLastClause() != null) {
- if (ctx.previousUntilLastClause().DURATION_LITERAL() != null) {
- preRange =
- DatetimeUtils.convertDurationStrToLong(
- ctx.previousUntilLastClause().DURATION_LITERAL().getText());
+ int defaultFillInterval = IoTDBDescriptor.getInstance().getConfig().getDefaultFillInterval();
+
+ if (ctx.linearClause() != null) { // linear
+ if (ctx.linearClause().DURATION_LITERAL(0) != null) {
+ String beforeStr = ctx.linearClause().DURATION_LITERAL(0).getText();
+ String afterStr = ctx.linearClause().DURATION_LITERAL(1).getText();
+ fill = new LinearFill(beforeStr, afterStr);
} else {
- preRange = IoTDBDescriptor.getInstance().getConfig().getDefaultFillInterval();
+ fill = new LinearFill(defaultFillInterval, defaultFillInterval);
}
- fill = new PreviousFill(preRange, true);
- } else {
+ } else if (ctx.previousClause() != null) { // previous
if (ctx.previousClause().DURATION_LITERAL() != null) {
- preRange =
- DatetimeUtils.convertDurationStrToLong(
- ctx.previousClause().DURATION_LITERAL().getText());
+ String preRangeStr = ctx.previousClause().DURATION_LITERAL().getText();
+ fill = new PreviousFill(preRangeStr);
} else {
- preRange = IoTDBDescriptor.getInstance().getConfig().getDefaultFillInterval();
+ fill = new PreviousFill(defaultFillInterval);
+ }
+ } else if (ctx.specificValueClause() != null) {
+ throw new SQLParserException("fill all doesn't support value fill");
+ } else { // previous until last
+ if (ctx.previousUntilLastClause().DURATION_LITERAL() != null) {
+ String preRangeStr = ctx.previousUntilLastClause().DURATION_LITERAL().getText();
+ fill = new PreviousFill(preRangeStr, true);
+ } else {
+ fill = new PreviousFill(defaultFillInterval, true);
}
- fill = new PreviousFill(preRange);
}
+
for (TSDataType tsDataType : TSDataType.values()) {
+ if (tsDataType == TSDataType.VECTOR) {
+ // TODO: TSDataType VECTOR
+ continue;
+ }
+ if (fill instanceof LinearFill
+ && (tsDataType == TSDataType.BOOLEAN || tsDataType == TSDataType.TEXT)) {
+ continue;
+ }
fillTypes.put(tsDataType, fill.copy());
}
}
@@ -1235,7 +1258,12 @@ public class IoTDBSqlVisitor extends IoTDBSqlParserBaseVisitor<Operator> {
private void parsePrimitiveTypeClause(
IoTDBSqlParser.TypeClauseContext ctx, Map<TSDataType, IFill> fillTypes) {
TSDataType dataType = parseType(ctx.dataType.getText());
- if (ctx.linearClause() != null && dataType == TSDataType.TEXT) {
+ if (dataType == TSDataType.VECTOR) {
+ throw new SQLParserException(String.format("type %s cannot use fill function", dataType));
+ }
+
+ if (ctx.linearClause() != null
+ && (dataType == TSDataType.TEXT || dataType == TSDataType.BOOLEAN)) {
throw new SQLParserException(
String.format(
"type %s cannot use %s fill function",
@@ -1246,26 +1274,21 @@ public class IoTDBSqlVisitor extends IoTDBSqlParserBaseVisitor<Operator> {
if (ctx.linearClause() != null) { // linear
if (ctx.linearClause().DURATION_LITERAL(0) != null) {
- long beforeRange =
- DatetimeUtils.convertDurationStrToLong(
- ctx.linearClause().DURATION_LITERAL(0).getText());
- long afterRange =
- DatetimeUtils.convertDurationStrToLong(
- ctx.linearClause().DURATION_LITERAL(1).getText());
- fillTypes.put(dataType, new LinearFill(beforeRange, afterRange));
+ String beforeRangeStr = ctx.linearClause().DURATION_LITERAL(0).getText();
+ String afterRangeStr = ctx.linearClause().DURATION_LITERAL(1).getText();
+ LinearFill fill = new LinearFill(beforeRangeStr, afterRangeStr);
+ fillTypes.put(dataType, fill);
} else {
fillTypes.put(dataType, new LinearFill(defaultFillInterval, defaultFillInterval));
}
} else if (ctx.previousClause() != null) { // previous
if (ctx.previousClause().DURATION_LITERAL() != null) {
- long preRange =
- DatetimeUtils.convertDurationStrToLong(
- ctx.previousClause().DURATION_LITERAL().getText());
- fillTypes.put(dataType, new PreviousFill(preRange));
+ String beforeStr = ctx.previousClause().DURATION_LITERAL().getText();
+ fillTypes.put(dataType, new PreviousFill(beforeStr));
} else {
fillTypes.put(dataType, new PreviousFill(defaultFillInterval));
}
- } else if (ctx.specificValueClause() != null) {
+ } else if (ctx.specificValueClause() != null) { // value
if (ctx.specificValueClause().constant() != null) {
fillTypes.put(
dataType, new ValueFill(ctx.specificValueClause().constant().getText(), dataType));
@@ -1274,10 +1297,8 @@ public class IoTDBSqlVisitor extends IoTDBSqlParserBaseVisitor<Operator> {
}
} else { // previous until last
if (ctx.previousUntilLastClause().DURATION_LITERAL() != null) {
- long preRange =
- DatetimeUtils.convertDurationStrToLong(
- ctx.previousUntilLastClause().DURATION_LITERAL().getText());
- fillTypes.put(dataType, new PreviousFill(preRange, true));
+ String preRangeStr = ctx.previousUntilLastClause().DURATION_LITERAL().getText();
+ fillTypes.put(dataType, new PreviousFill(preRangeStr, true));
} else {
fillTypes.put(dataType, new PreviousFill(defaultFillInterval, true));
}
diff --git a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByEngineDataSet.java b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByEngineDataSet.java
index 690f4a6..39aa84f 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByEngineDataSet.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByEngineDataSet.java
@@ -47,10 +47,9 @@ public abstract class GroupByEngineDataSet extends QueryDataSet {
protected boolean hasCachedTimeInterval;
protected boolean leftCRightO;
- private boolean isIntervalByMonth = false;
- private boolean isSlidingStepByMonth = false;
- protected int intervalTimes;
- private static final long MS_TO_MONTH = 30 * 86400_000L;
+ protected boolean isIntervalByMonth = false;
+ protected boolean isSlidingStepByMonth = false;
+ public static final long MS_TO_MONTH = 30 * 86400_000L;
protected AggregateResult[] curAggregateResults;
public GroupByEngineDataSet() {}
@@ -66,6 +65,84 @@ public abstract class GroupByEngineDataSet extends QueryDataSet {
initGroupByEngineDataSetFields(context, groupByTimePlan);
}
+ protected Pair<Long, Long> getFirstTimeRange() {
+ long retEndTime;
+ if (isIntervalByMonth) {
+ // calculate interval length by natural month based on startTime
+ // ie. startTIme = 1/31, interval = 1mo, curEndTime will be set to 2/29
+ retEndTime = Math.min(calcIntervalByMonth(startTime, interval), endTime);
+ } else {
+ retEndTime = Math.min(startTime + interval, endTime);
+ }
+ return new Pair<>(startTime, retEndTime);
+ }
+
+ protected Pair<Long, Long> getLastTimeRange() {
+ long retStartTime;
+ long retEndTime;
+ long queryRange = endTime - startTime;
+ long intervalNum;
+
+ if (isSlidingStepByMonth) {
+ intervalNum = (long) Math.ceil(queryRange / (double) (slidingStep * MS_TO_MONTH));
+ retStartTime = calcIntervalByMonth(startTime, intervalNum * slidingStep);
+ while (retStartTime >= endTime) {
+ intervalNum -= 1;
+ retStartTime = calcIntervalByMonth(startTime, intervalNum * slidingStep);
+ }
+ } else {
+ intervalNum = (long) Math.ceil(queryRange / (double) slidingStep);
+ retStartTime = slidingStep * (intervalNum - 1) + startTime;
+ }
+
+ if (isIntervalByMonth) {
+ // calculate interval length by natural month based on curStartTime
+ // ie. startTIme = 1/31, interval = 1mo, curEndTime will be set to 2/29
+ retEndTime = Math.min(calcIntervalByMonth(retStartTime, interval), endTime);
+ } else {
+ retEndTime = Math.min(retStartTime + interval, endTime);
+ }
+
+ return new Pair<>(retStartTime, retEndTime);
+ }
+
+ protected Pair<Long, Long> getNextTimeRange(
+ long curStartTime, boolean isAscending, boolean isInside) {
+ long retStartTime, retEndTime;
+
+ if (isAscending) {
+ if (isSlidingStepByMonth) {
+ retStartTime = calcIntervalByMonth(curStartTime, (int) (slidingStep));
+ } else {
+ retStartTime = curStartTime + slidingStep;
+ }
+ // This is an open interval , [0-100)
+ if (retStartTime >= endTime && isInside) {
+ return null;
+ }
+ } else {
+ if (isSlidingStepByMonth) {
+ retStartTime = calcIntervalByMonth(curStartTime, (int) (-slidingStep));
+ } else {
+ retStartTime = curStartTime - slidingStep;
+ }
+ if (retStartTime < startTime && isInside) {
+ return null;
+ }
+ }
+
+ if (isIntervalByMonth) {
+ retEndTime = calcIntervalByMonth(retStartTime, (int) (interval));
+ } else {
+ retEndTime = retStartTime + interval;
+ }
+ if (isInside) {
+ retEndTime = Math.min(retEndTime, endTime);
+ }
+
+ return new Pair<>(retStartTime, retEndTime);
+ }
+
protected void initGroupByEngineDataSetFields(
QueryContext context, GroupByTimePlan groupByTimePlan) {
this.queryId = context.getQueryId();
@@ -82,89 +159,59 @@ public abstract class GroupByEngineDataSet extends QueryDataSet {
interval = interval / MS_TO_MONTH;
}
- // find the startTime of the first aggregation interval
- if (ascending) {
- curStartTime = startTime;
- } else {
- long queryRange = endTime - startTime;
- // calculate the total interval number
- long intervalNum = (long) Math.ceil(queryRange / (double) slidingStep);
- if (isSlidingStepByMonth) {
- intervalTimes = (int) intervalNum - 1;
- curStartTime = calcIntervalByMonth(intervalTimes * slidingStep / MS_TO_MONTH);
- } else {
- curStartTime = slidingStep * (intervalNum - 1) + startTime;
- }
- }
-
if (isSlidingStepByMonth) {
slidingStep = slidingStep / MS_TO_MONTH;
}
- if (isIntervalByMonth) {
- // calculate interval length by natural month based on curStartTime
- // ie. startTIme = 1/31, interval = 1mo, curEndTime will be set to 2/29
- curEndTime = Math.min(calcIntervalByMonth(interval + slidingStep * intervalTimes), endTime);
+ // find the first aggregation interval
+ Pair<Long, Long> retTimeRange;
+ if (ascending) {
+ retTimeRange = getFirstTimeRange();
} else {
- curEndTime = Math.min(curStartTime + interval, endTime);
+ retTimeRange = getLastTimeRange();
}
+ curStartTime = retTimeRange.left;
+ curEndTime = retTimeRange.right;
this.hasCachedTimeInterval = true;
}
@Override
public boolean hasNextWithoutConstraint() {
- long curSlidingStep = slidingStep;
- long curInterval = interval;
// has cached
if (hasCachedTimeInterval) {
return true;
}
- // for group by natural months addition
- intervalTimes += ascending ? 1 : -1;
-
- if (ascending) {
- if (isSlidingStepByMonth) {
- curStartTime = calcIntervalByMonth(slidingStep * intervalTimes);
- } else {
- curStartTime += curSlidingStep;
- }
- // This is an open interval , [0-100)
- if (curStartTime >= endTime) {
- return false;
- }
- } else {
- if (isSlidingStepByMonth) {
- curStartTime = calcIntervalByMonth(slidingStep * intervalTimes);
- } else {
- curStartTime -= curSlidingStep;
- }
- if (curStartTime < startTime) {
- return false;
- }
+ // find the next aggregation interval
+ Pair<Long, Long> nextTimeRange = getNextTimeRange(curStartTime, ascending, true);
+ if (nextTimeRange == null) {
+ return false;
}
+ curStartTime = nextTimeRange.left;
+ curEndTime = nextTimeRange.right;
hasCachedTimeInterval = true;
- if (isIntervalByMonth) {
- curEndTime = Math.min(calcIntervalByMonth(intervalTimes * slidingStep + interval), endTime);
- } else {
- curEndTime = Math.min(curStartTime + curInterval, endTime);
- }
return true;
}
/**
- * add natural months based on the first starttime to avoid edge cases, ie 2/28
+ * add natural months based on the startTime to avoid edge cases, ie 2/28
*
+ * @param startTime current start time
* @param numMonths numMonths is updated in hasNextWithoutConstraint()
- * @return curStartTime
+ * @return nextStartTime
*/
- public long calcIntervalByMonth(long numMonths) {
+ public long calcIntervalByMonth(long startTime, long numMonths) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(SessionManager.getInstance().getCurrSessionTimeZone());
calendar.setTimeInMillis(startTime);
+ boolean isLastDayOfMonth =
+ calendar.get(Calendar.DAY_OF_MONTH) == calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
calendar.add(Calendar.MONTH, (int) (numMonths));
+ if (isLastDayOfMonth) {
+ calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
+ }
return calendar.getTimeInMillis();
}
diff --git a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByFillDataSet.java b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByFillDataSet.java
deleted file mode 100644
index 11e82cd..0000000
--- a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByFillDataSet.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.iotdb.db.query.dataset.groupby;
-
-import org.apache.iotdb.db.conf.IoTDBDescriptor;
-import org.apache.iotdb.db.engine.StorageEngine;
-import org.apache.iotdb.db.engine.storagegroup.StorageGroupProcessor;
-import org.apache.iotdb.db.exception.StorageEngineException;
-import org.apache.iotdb.db.exception.query.QueryProcessException;
-import org.apache.iotdb.db.metadata.PartialPath;
-import org.apache.iotdb.db.qp.physical.crud.GroupByTimeFillPlan;
-import org.apache.iotdb.db.query.context.QueryContext;
-import org.apache.iotdb.db.query.executor.LastQueryExecutor;
-import org.apache.iotdb.db.query.executor.fill.IFill;
-import org.apache.iotdb.db.query.executor.fill.PreviousFill;
-import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.read.TimeValuePair;
-import org.apache.iotdb.tsfile.read.common.Field;
-import org.apache.iotdb.tsfile.read.common.RowRecord;
-import org.apache.iotdb.tsfile.read.query.dataset.QueryDataSet;
-import org.apache.iotdb.tsfile.utils.Pair;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-public class GroupByFillDataSet extends QueryDataSet {
-
- private GroupByEngineDataSet groupByEngineDataSet;
- private Map<TSDataType, IFill> fillTypes;
- // the first value for each time series
- private Object[] previousValue;
- private long[] previousTime;
- // last timestamp for each time series
- private long[] lastTimeArray;
- private TimeValuePair[] firstNotNullTV;
- private boolean isPeekEnded = false;
-
- public GroupByFillDataSet(
- List<PartialPath> paths,
- List<TSDataType> dataTypes,
- GroupByEngineDataSet groupByEngineDataSet,
- Map<TSDataType, IFill> fillTypes,
- QueryContext context,
- GroupByTimeFillPlan groupByFillPlan)
- throws StorageEngineException, IOException, QueryProcessException {
- super(new ArrayList<>(paths), dataTypes, groupByFillPlan.isAscending());
- this.groupByEngineDataSet = groupByEngineDataSet;
- this.fillTypes = fillTypes;
- List<StorageGroupProcessor> list = StorageEngine.getInstance().mergeLock(paths);
- try {
- initPreviousParis(context, groupByFillPlan);
- initLastTimeArray(context, groupByFillPlan);
- } finally {
- StorageEngine.getInstance().mergeUnLock(list);
- }
- }
-
- private void initPreviousParis(QueryContext context, GroupByTimeFillPlan groupByFillPlan)
- throws StorageEngineException, IOException, QueryProcessException {
- previousValue = new Object[paths.size()];
- previousTime = new long[paths.size()];
- firstNotNullTV = new TimeValuePair[paths.size()];
-
- for (int i = 0; i < paths.size(); i++) {
- PartialPath path = (PartialPath) paths.get(i);
- TSDataType dataType = dataTypes.get(i);
- IFill fill;
- if (fillTypes.containsKey(dataType)) {
- fill =
- new PreviousFill(
- dataType,
- groupByEngineDataSet.getStartTime(),
- ((PreviousFill) fillTypes.get(dataType)).getBeforeRange(),
- ((PreviousFill) fillTypes.get(dataType)).isUntilLast());
- } else {
- fill =
- new PreviousFill(
- dataType,
- groupByEngineDataSet.getStartTime(),
- IoTDBDescriptor.getInstance().getConfig().getDefaultFillInterval());
- }
- fill.configureFill(
- path,
- dataType,
- groupByEngineDataSet.getStartTime(),
- groupByFillPlan.getAllMeasurementsInDevice(path.getDevice()),
- context);
-
- firstNotNullTV[i] = fill.getFillResult();
- TimeValuePair timeValuePair = firstNotNullTV[i];
- previousValue[i] = null;
- previousTime[i] = Long.MAX_VALUE;
- if (ascending && timeValuePair != null && timeValuePair.getValue() != null) {
- previousValue[i] = timeValuePair.getValue().getValue();
- previousTime[i] = timeValuePair.getTimestamp();
- }
- }
- }
-
- private void initLastTimeArray(QueryContext context, GroupByTimeFillPlan groupByFillPlan)
- throws IOException, StorageEngineException, QueryProcessException {
- lastTimeArray = new long[paths.size()];
- Arrays.fill(lastTimeArray, Long.MAX_VALUE);
- List<PartialPath> seriesPaths = new ArrayList<>();
- for (int i = 0; i < paths.size(); i++) {
- seriesPaths.add((PartialPath) paths.get(i));
- }
- List<Pair<Boolean, TimeValuePair>> lastValueContainer =
- LastQueryExecutor.calculateLastPairForSeriesLocally(
- seriesPaths, dataTypes, context, null, groupByFillPlan.getDeviceToMeasurements());
- for (int i = 0; i < lastValueContainer.size(); i++) {
- if (Boolean.TRUE.equals(lastValueContainer.get(i).left)) {
- lastTimeArray[i] = lastValueContainer.get(i).right.getTimestamp();
- }
- }
- }
-
- @Override
- public boolean hasNextWithoutConstraint() {
- return groupByEngineDataSet.hasNextWithoutConstraint();
- }
-
- @Override
- @SuppressWarnings("squid:S3776")
- public RowRecord nextWithoutConstraint() throws IOException {
- RowRecord rowRecord = groupByEngineDataSet.nextWithoutConstraint();
-
- for (int i = 0; i < paths.size(); i++) {
- Field field = rowRecord.getFields().get(i);
- // current group by result is null
- if (field == null || field.getDataType() == null) {
- TSDataType tsDataType = dataTypes.get(i);
- // for desc query peek previous time and value
- if (!ascending && !isPeekEnded && !canUseCacheData(rowRecord, tsDataType, i)) {
- fillCache(i);
- }
-
- if (canUseCacheData(rowRecord, tsDataType, i)) {
- rowRecord.getFields().set(i, Field.getField(previousValue[i], tsDataType));
- }
- } else {
- // use now value update previous value
- previousValue[i] = field.getObjectValue(field.getDataType());
- previousTime[i] = rowRecord.getTimestamp();
- }
- }
- return rowRecord;
- }
-
- private void fillCache(int i) throws IOException {
- Pair<Long, Object> data = groupByEngineDataSet.peekNextNotNullValue(paths.get(i), i);
- if (data == null) {
- isPeekEnded = true;
- previousTime[i] = Long.MIN_VALUE;
- previousValue[i] = null;
- if (!firstCacheIsEmpty(i)) {
- previousValue[i] = firstNotNullTV[i].getValue().getValue();
- previousTime[i] = firstNotNullTV[i].getTimestamp();
- }
- } else {
- previousValue[i] = data.right;
- previousTime[i] = data.left;
- }
- }
-
- // the previous value is not null
- // and (fill type is not previous until last or now time is before last time)
- // and (previous before range is not limited or previous before range contains the previous
- // interval)
- private boolean canUseCacheData(RowRecord rowRecord, TSDataType tsDataType, int i) {
- PreviousFill previousFill = (PreviousFill) fillTypes.get(tsDataType);
- return !cacheIsEmpty(i)
- && satisfyTime(rowRecord, tsDataType, previousFill, lastTimeArray[i])
- && satisfyRange(tsDataType, previousFill)
- && isIncreasingTime(rowRecord, previousTime[i]);
- }
-
- private boolean isIncreasingTime(RowRecord rowRecord, long time) {
- return rowRecord.getTimestamp() >= time;
- }
-
- private boolean satisfyTime(
- RowRecord rowRecord, TSDataType tsDataType, PreviousFill previousFill, long lastTime) {
- return (fillTypes.containsKey(tsDataType) && !previousFill.isUntilLast())
- || rowRecord.getTimestamp() <= lastTime;
- }
-
- private boolean satisfyRange(TSDataType tsDataType, PreviousFill previousFill) {
- return !fillTypes.containsKey(tsDataType)
- || previousFill.getBeforeRange() < 0
- || previousFill.getBeforeRange() >= groupByEngineDataSet.interval;
- }
-
- private boolean cacheIsEmpty(int i) {
- return previousValue[i] == null;
- }
-
- private boolean firstCacheIsEmpty(int i) {
- return firstNotNullTV[i] == null || firstNotNullTV[i].getValue() == null;
- }
-}
diff --git a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByFillWithoutValueFilterDataSet.java b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByFillWithoutValueFilterDataSet.java
new file mode 100644
index 0000000..2eab664
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByFillWithoutValueFilterDataSet.java
@@ -0,0 +1,577 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.iotdb.db.query.dataset.groupby;
+
+import org.apache.iotdb.db.engine.StorageEngine;
+import org.apache.iotdb.db.engine.storagegroup.StorageGroupProcessor;
+import org.apache.iotdb.db.exception.StorageEngineException;
+import org.apache.iotdb.db.exception.query.QueryProcessException;
+import org.apache.iotdb.db.exception.query.UnSupportedFillTypeException;
+import org.apache.iotdb.db.metadata.PartialPath;
+import org.apache.iotdb.db.qp.physical.crud.GroupByTimeFillPlan;
+import org.apache.iotdb.db.query.aggregation.AggregateResult;
+import org.apache.iotdb.db.query.aggregation.impl.CountAggrResult;
+import org.apache.iotdb.db.query.context.QueryContext;
+import org.apache.iotdb.db.query.executor.fill.IFill;
+import org.apache.iotdb.db.query.executor.fill.LinearFill;
+import org.apache.iotdb.db.query.executor.fill.PreviousFill;
+import org.apache.iotdb.db.query.executor.fill.ValueFill;
+import org.apache.iotdb.db.query.factory.AggregateResultFactory;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.read.TimeValuePair;
+import org.apache.iotdb.tsfile.read.common.Path;
+import org.apache.iotdb.tsfile.read.common.RowRecord;
+import org.apache.iotdb.tsfile.read.filter.GroupByFilter;
+import org.apache.iotdb.tsfile.read.filter.basic.Filter;
+import org.apache.iotdb.tsfile.utils.Pair;
+import org.apache.iotdb.tsfile.utils.TsPrimitiveType;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+public class GroupByFillWithoutValueFilterDataSet extends GroupByWithoutValueFilterDataSet {
+
+ private static final Logger logger =
+ LoggerFactory.getLogger(GroupByFillWithoutValueFilterDataSet.class);
+
+ private Map<TSDataType, IFill> fillTypes;
+ private final List<PartialPath> deduplicatedPaths;
+ private final List<String> aggregations;
+ private Map<PartialPath, GroupByExecutor> extraPreviousExecutors = null;
+ private Map<PartialPath, GroupByExecutor> extraNextExecutors = null;
+
+ // the extra previous means first not null value before startTime
+ // used to fill result before the first not null data
+ private Object[] extraPreviousValues;
+ private long[] extraPreviousTimes;
+
+ // the previous value for each time series, which means
+ // first not null value GEQ curStartTime in order asc
+ // second not null value GEQ curStartTime in order desc
+ private Object[] previousValues;
+ private long[] previousTimes;
+
+ // the extra next means first not null value after endTime
+ // used to fill result after the last not null data
+ private Object[] extraNextValues;
+ private long[] extraNextTimes;
+
+ // the next value for each time series, which means
+ // first not null value LEQ curStartTime in order desc
+ // second not null value LEQ curStartTime in order asc
+ private Object[] nextValues;
+ private long[] nextTimes;
+
+ // the result datatype for each time series
+ private TSDataType[] resultDataType;
+
+ // the next query time range of each path
+ private long[] queryStartTimes;
+ private long[] queryEndTimes;
+ private boolean[] hasCachedQueryInterval;
+
+ public GroupByFillWithoutValueFilterDataSet(
+ QueryContext context, GroupByTimeFillPlan groupByTimeFillPlan)
+ throws QueryProcessException, StorageEngineException {
+ super(context, groupByTimeFillPlan);
+ this.aggregations = groupByTimeFillPlan.getDeduplicatedAggregations();
+
+ this.deduplicatedPaths = new ArrayList<>();
+ for (Path path : paths) {
+ PartialPath partialPath = (PartialPath) path;
+ if (!deduplicatedPaths.contains(partialPath)) {
+ deduplicatedPaths.add(partialPath);
+ }
+ }
+
+ initArrays();
+ initExtraExecutors(context, groupByTimeFillPlan);
+ if (extraPreviousExecutors != null) {
+ initExtraArrays(extraPreviousValues, extraPreviousTimes, true, extraPreviousExecutors);
+ }
+ if (extraNextExecutors != null) {
+ initExtraArrays(extraNextValues, extraNextTimes, false, extraNextExecutors);
+ }
+ initCachedTimesAndValues();
+ }
+
+ private void initArrays() {
+ extraPreviousValues = new Object[aggregations.size()];
+ extraPreviousTimes = new long[aggregations.size()];
+ previousValues = new Object[aggregations.size()];
+ previousTimes = new long[aggregations.size()];
+ extraNextValues = new Object[aggregations.size()];
+ extraNextTimes = new long[aggregations.size()];
+ nextValues = new Object[aggregations.size()];
+ nextTimes = new long[aggregations.size()];
+ Arrays.fill(extraPreviousValues, null);
+ Arrays.fill(extraPreviousTimes, Long.MIN_VALUE);
+ Arrays.fill(previousValues, null);
+ Arrays.fill(previousTimes, Long.MIN_VALUE);
+ Arrays.fill(extraNextValues, null);
+ Arrays.fill(extraNextTimes, Long.MAX_VALUE);
+ Arrays.fill(nextValues, null);
+ Arrays.fill(nextTimes, Long.MAX_VALUE);
+
+ queryStartTimes = new long[paths.size()];
+ queryEndTimes = new long[paths.size()];
+ hasCachedQueryInterval = new boolean[paths.size()];
+ resultDataType = new TSDataType[aggregations.size()];
+ Arrays.fill(queryStartTimes, curStartTime);
+ Arrays.fill(queryEndTimes, curEndTime);
+ Arrays.fill(hasCachedQueryInterval, true);
+ for (PartialPath deduplicatedPath : deduplicatedPaths) {
+ List<Integer> indexes = resultIndexes.get(deduplicatedPath);
+ for (int index : indexes) {
+ switch (aggregations.get(index)) {
+ case "avg":
+ case "sum":
+ resultDataType[index] = TSDataType.DOUBLE;
+ break;
+ case "count":
+ case "max_time":
+ case "min_time":
+ resultDataType[index] = TSDataType.INT64;
+ break;
+ case "first_value":
+ case "last_value":
+ case "max_value":
+ case "min_value":
+ resultDataType[index] = dataTypes.get(index);
+ break;
+ }
+ }
+ }
+ }
+
+ private void getGroupByExecutors(
+ Map<PartialPath, GroupByExecutor> extraExecutors,
+ QueryContext context,
+ GroupByTimeFillPlan groupByTimeFillPlan,
+ Filter timeFilter,
+ boolean isAscending)
+ throws StorageEngineException, QueryProcessException {
+ List<StorageGroupProcessor> list =
+ StorageEngine.getInstance()
+ .mergeLock(paths.stream().map(p -> (PartialPath) p).collect(Collectors.toList()));
+ try {
+ // init resultIndexes, group result indexes by path
+ for (int i = 0; i < paths.size(); i++) {
+ PartialPath path = (PartialPath) paths.get(i);
+ if (!extraExecutors.containsKey(path)) {
+ // init GroupByExecutor
+ extraExecutors.put(
+ path,
+ getGroupByExecutor(
+ path,
+ groupByTimeFillPlan.getAllMeasurementsInDevice(path.getDevice()),
+ dataTypes.get(i),
+ context,
+ timeFilter.copy(),
+ null,
+ isAscending));
+ }
+ AggregateResult aggrResult =
+ AggregateResultFactory.getAggrResultByName(
+ groupByTimeFillPlan.getDeduplicatedAggregations().get(i),
+ dataTypes.get(i),
+ ascending);
+ extraExecutors.get(path).addAggregateResult(aggrResult);
+ }
+ } finally {
+ StorageEngine.getInstance().mergeUnLock(list);
+ }
+ }
+
+ /* Init extra path executors to query data outside the original group by query */
+ private void initExtraExecutors(QueryContext context, GroupByTimeFillPlan groupByTimeFillPlan)
+ throws StorageEngineException, QueryProcessException {
+ long minQueryStartTime = Long.MAX_VALUE;
+ long maxQueryEndTime = Long.MIN_VALUE;
+ this.fillTypes = groupByTimeFillPlan.getFillType();
+ for (Map.Entry<TSDataType, IFill> IFillEntry : fillTypes.entrySet()) {
+ IFill fill = IFillEntry.getValue();
+ if (fill instanceof PreviousFill) {
+ fill.convertRange(startTime, endTime);
+ minQueryStartTime = Math.min(minQueryStartTime, fill.getQueryStartTime());
+ } else if (fill instanceof LinearFill) {
+ fill.convertRange(startTime, endTime);
+ minQueryStartTime = Math.min(minQueryStartTime, fill.getQueryStartTime());
+ maxQueryEndTime = Math.max(maxQueryEndTime, fill.getQueryEndTime());
+ }
+ }
+
+ if (minQueryStartTime < Long.MAX_VALUE) {
+ extraPreviousExecutors = new HashMap<>();
+
+ long queryRange = minQueryStartTime - startTime;
+ long extraStartTime, intervalNum;
+ if (isSlidingStepByMonth) {
+ intervalNum = (long) Math.ceil(queryRange / (double) (slidingStep * MS_TO_MONTH));
+ extraStartTime = calcIntervalByMonth(startTime, intervalNum * slidingStep);
+ while (extraStartTime < minQueryStartTime) {
+ intervalNum += 1;
+ extraStartTime = calcIntervalByMonth(startTime, intervalNum * slidingStep);
+ }
+ } else {
+ intervalNum = (long) Math.ceil(queryRange / (double) slidingStep);
+ extraStartTime = slidingStep * intervalNum + startTime;
+ }
+
+ Filter timeFilter = new GroupByFilter(interval, slidingStep, extraStartTime, startTime);
+ getGroupByExecutors(extraPreviousExecutors, context, groupByTimeFillPlan, timeFilter, false);
+ }
+
+ if (maxQueryEndTime > Long.MIN_VALUE) {
+ extraNextExecutors = new HashMap<>();
+ Pair<Long, Long> lastTimeRange = getLastTimeRange();
+ lastTimeRange = getNextTimeRange(lastTimeRange.left, true, false);
+ Filter timeFilter =
+ new GroupByFilter(interval, slidingStep, lastTimeRange.left, maxQueryEndTime);
+ getGroupByExecutors(extraNextExecutors, context, groupByTimeFillPlan, timeFilter, true);
+ }
+ }
+
+ /* check if specified path has next extra range */
+ private boolean pathHasExtra(int pathId, boolean isExtraPrevious, long extraStartTime) {
+ List<Integer> Indexes = resultIndexes.get(deduplicatedPaths.get(pathId));
+ for (int resultIndex : Indexes) {
+ if (isExtraPrevious && extraPreviousValues[resultIndex] != null) {
+ continue;
+ } else if (!isExtraPrevious && extraNextValues[resultIndex] != null) {
+ continue;
+ }
+
+ IFill fill = fillTypes.get(resultDataType[resultIndex]);
+ if (fill == null) {
+ continue;
+ }
+ if (fill instanceof PreviousFill && isExtraPrevious) {
+ if (fill.getQueryStartTime() <= extraStartTime) {
+ return true;
+ }
+ } else if (fill instanceof LinearFill) {
+ if (isExtraPrevious) {
+ if (fill.getQueryStartTime() <= extraStartTime) {
+ return true;
+ }
+ } else {
+ if (extraStartTime < fill.getQueryEndTime()) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private void initExtraArrays(
+ Object[] extraValues,
+ long[] extraTimes,
+ boolean isExtraPrevious,
+ Map<PartialPath, GroupByExecutor> extraExecutors)
+ throws QueryProcessException {
+ for (int pathId = 0; pathId < deduplicatedPaths.size(); pathId++) {
+ GroupByExecutor executor = extraExecutors.get(deduplicatedPaths.get(pathId));
+ List<Integer> Indexes = resultIndexes.get(deduplicatedPaths.get(pathId));
+
+ Pair<Long, Long> extraTimeRange;
+ if (isExtraPrevious) {
+ extraTimeRange = getFirstTimeRange();
+ } else {
+ extraTimeRange = getLastTimeRange();
+ }
+
+ extraTimeRange = getNextTimeRange(extraTimeRange.left, !isExtraPrevious, false);
+ try {
+ while (pathHasExtra(pathId, isExtraPrevious, extraTimeRange.left)) {
+ List<AggregateResult> aggregations =
+ executor.calcResult(extraTimeRange.left, extraTimeRange.right);
+ if (!resultIsNull(aggregations)) {
+ // we check extra time range in single path together,
+ // thus the extra result will be cached together
+ for (int i = 0; i < aggregations.size(); i++) {
+ if (extraValues[Indexes.get(i)] == null) {
+ extraValues[Indexes.get(i)] = aggregations.get(i).getResult();
+ extraTimes[Indexes.get(i)] = extraTimeRange.left;
+ }
+ }
+ }
+
+ extraTimeRange = getNextTimeRange(extraTimeRange.left, !isExtraPrevious, false);
+ }
+ } catch (IOException e) {
+ throw new QueryProcessException(e.getMessage());
+ }
+ }
+ }
+
+ private boolean pathHasNext(int pathId) {
+ // has cached
+ if (hasCachedQueryInterval[pathId]) {
+ return true;
+ }
+
+ // find the next aggregation interval
+ Pair<Long, Long> nextTimeRange = getNextTimeRange(queryStartTimes[pathId], ascending, true);
+ if (nextTimeRange == null) {
+ return false;
+ }
+ queryStartTimes[pathId] = nextTimeRange.left;
+ queryEndTimes[pathId] = nextTimeRange.right;
+
+ hasCachedQueryInterval[pathId] = true;
+ return true;
+ }
+
+ /* If result is null or CountAggrResult is 0, then result is NULL */
+ private boolean resultIsNull(List<AggregateResult> aggregateResults) {
+ AggregateResult result = aggregateResults.get(0);
+ if (result.getResult() == null) {
+ return true;
+ } else {
+ return result instanceof CountAggrResult && (long) result.getResult() == 0;
+ }
+ }
+
+ private void pathGetNext(int pathId) throws IOException {
+ GroupByExecutor executor = pathExecutors.get(deduplicatedPaths.get(pathId));
+ List<Integer> resultIndex = resultIndexes.get(deduplicatedPaths.get(pathId));
+
+ // Slide value and time
+ pathSlideNext(pathId);
+
+ List<AggregateResult> aggregations;
+ try {
+ // get second not null aggregate results
+ aggregations = executor.calcResult(queryStartTimes[pathId], queryEndTimes[pathId]);
+ hasCachedQueryInterval[pathId] = false;
+ while (resultIsNull(aggregations) && pathHasNext(pathId)) {
+ aggregations = executor.calcResult(queryStartTimes[pathId], queryEndTimes[pathId]);
+ hasCachedQueryInterval[pathId] = false;
+ }
+ } catch (QueryProcessException e) {
+ logger.error("GroupByFillWithoutValueFilterDataSet execute has error: ", e);
+ throw new IOException(e.getMessage(), e);
+ }
+
+ if (resultIsNull(aggregations)) {
+ pathSlide(pathId);
+ } else {
+ for (int i = 0; i < aggregations.size(); i++) {
+ int Index = resultIndex.get(i);
+ if (ascending) {
+ nextValues[Index] = aggregations.get(i).getResult();
+ nextTimes[Index] = queryStartTimes[pathId];
+ } else {
+ previousValues[Index] = aggregations.get(i).getResult();
+ previousTimes[Index] = queryStartTimes[pathId];
+ }
+ }
+ }
+
+ hasCachedQueryInterval[pathId] = false;
+ }
+
+ private void pathSlideNext(int pathId) {
+ List<Integer> resultIndex = resultIndexes.get(deduplicatedPaths.get(pathId));
+ if (ascending) {
+ for (int resultId : resultIndex) {
+ previousValues[resultId] = nextValues[resultId];
+ previousTimes[resultId] = nextTimes[resultId];
+ nextValues[resultId] = null;
+ nextTimes[resultId] = Long.MAX_VALUE;
+ }
+ } else {
+ for (int resultId : resultIndex) {
+ nextValues[resultId] = previousValues[resultId];
+ nextTimes[resultId] = previousTimes[resultId];
+ previousValues[resultId] = null;
+ previousTimes[resultId] = Long.MIN_VALUE;
+ }
+ }
+ }
+
+ private void pathSlideExtra(int pathId) {
+ List<Integer> resultIndex = resultIndexes.get(deduplicatedPaths.get(pathId));
+ if (ascending) {
+ for (int Index : resultIndex) {
+ nextValues[Index] = extraNextValues[Index];
+ nextTimes[Index] = extraNextTimes[Index];
+ }
+ } else {
+ for (int Index : resultIndex) {
+ previousValues[Index] = extraPreviousValues[Index];
+ previousTimes[Index] = extraPreviousTimes[Index];
+ }
+ }
+ }
+
+ private void pathSlide(int pathId) throws IOException {
+ if (pathHasNext(pathId)) {
+ pathGetNext(pathId);
+ } else {
+ pathSlideExtra(pathId);
+ }
+ }
+
+ /* Cache the previous and next query data before group by fill query */
+ private void initCachedTimesAndValues() throws QueryProcessException {
+ for (int pathId = 0; pathId < deduplicatedPaths.size(); pathId++) {
+ try {
+ pathSlide(pathId);
+ pathSlide(pathId);
+ } catch (IOException e) {
+ throw new QueryProcessException(e.getMessage());
+ }
+ }
+ }
+
+ private void fillRecord(
+ int resultId, RowRecord record, Pair<Long, Object> beforePair, Pair<Long, Object> afterPair)
+ throws IOException {
+ // Don't fill count aggregation
+ if (Objects.equals(aggregations.get(resultId), "count")) {
+ record.addField((long) 0, TSDataType.INT64);
+ return;
+ }
+
+ IFill fill = fillTypes.get(resultDataType[resultId]);
+ if (fill == null) {
+ record.addField(null);
+ return;
+ }
+
+ if (fill instanceof PreviousFill) {
+ if (beforePair.right != null
+ && (fill.getBeforeRange() == -1
+ || fill.insideBeforeRange(beforePair.left, record.getTimestamp()))
+ && ((!((PreviousFill) fill).isUntilLast())
+ || (afterPair.right != null && afterPair.left < endTime))) {
+ record.addField(beforePair.right, resultDataType[resultId]);
+ } else {
+ record.addField(null);
+ }
+ } else if (fill instanceof LinearFill) {
+ LinearFill linearFill = new LinearFill();
+ if (beforePair.right != null
+ && afterPair.right != null
+ && (fill.getBeforeRange() == -1
+ || fill.insideBeforeRange(beforePair.left, record.getTimestamp()))
+ && (fill.getAfterRange() == -1
+ || fill.insideAfterRange(afterPair.left, record.getTimestamp()))) {
+ try {
+ TimeValuePair filledPair =
+ linearFill.averageWithTimeAndDataType(
+ new TimeValuePair(
+ beforePair.left,
+ TsPrimitiveType.getByType(resultDataType[resultId], beforePair.right)),
+ new TimeValuePair(
+ afterPair.left,
+ TsPrimitiveType.getByType(resultDataType[resultId], afterPair.right)),
+ curStartTime,
+ resultDataType[resultId]);
+ record.addField(filledPair.getValue().getValue(), resultDataType[resultId]);
+ } catch (UnSupportedFillTypeException e) {
+ record.addField(null);
+ throw new IOException(e);
+ }
+ } else {
+ record.addField(null);
+ }
+ } else if (fill instanceof ValueFill) {
+ try {
+ TimeValuePair filledPair = fill.getFillResult();
+ record.addField(filledPair.getValue().getValue(), resultDataType[resultId]);
+ } catch (QueryProcessException | StorageEngineException e) {
+ throw new IOException(e);
+ }
+ }
+ }
+
+ @Override
+ public RowRecord nextWithoutConstraint() throws IOException {
+ if (!hasCachedTimeInterval) {
+ throw new IOException(
+ "need to call hasNext() before calling next() "
+ + "in GroupByFillWithoutValueFilterDataSet.");
+ }
+ hasCachedTimeInterval = false;
+ RowRecord record = new RowRecord(curStartTime);
+
+ boolean[] pathNeedSlide = new boolean[previousTimes.length];
+ Arrays.fill(pathNeedSlide, false);
+ for (int resultId = 0; resultId < previousTimes.length; resultId++) {
+ if (previousTimes[resultId] == curStartTime) {
+ record.addField(previousValues[resultId], resultDataType[resultId]);
+ if (!ascending) {
+ pathNeedSlide[resultId] = true;
+ }
+ } else if (nextTimes[resultId] == curStartTime) {
+ record.addField(nextValues[resultId], resultDataType[resultId]);
+ if (ascending) {
+ pathNeedSlide[resultId] = true;
+ }
+ } else if (previousTimes[resultId] < curStartTime && curStartTime < nextTimes[resultId]) {
+ fillRecord(
+ resultId,
+ record,
+ new Pair<>(previousTimes[resultId], previousValues[resultId]),
+ new Pair<>(nextTimes[resultId], nextValues[resultId]));
+ } else if (curStartTime < previousTimes[resultId]) {
+ fillRecord(
+ resultId,
+ record,
+ new Pair<>(extraPreviousTimes[resultId], extraPreviousValues[resultId]),
+ new Pair<>(previousTimes[resultId], previousValues[resultId]));
+ } else if (nextTimes[resultId] < curStartTime) {
+ fillRecord(
+ resultId,
+ record,
+ new Pair<>(nextTimes[resultId], nextValues[resultId]),
+ new Pair<>(extraNextTimes[resultId], extraNextValues[resultId]));
+ }
+ }
+
+ // Slide paths
+ // the aggregation results of one path are either all null or all not null,
+ // thus slide all results together
+ for (int pathId = 0; pathId < deduplicatedPaths.size(); pathId++) {
+ List<Integer> resultIndex = resultIndexes.get(deduplicatedPaths.get(pathId));
+ if (pathNeedSlide[resultIndex.get(0)]) {
+ pathSlide(pathId);
+ }
+ }
+
+ if (!leftCRightO) {
+ record.setTimestamp(curEndTime - 1);
+ }
+ return record;
+ }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByWithValueFilterDataSet.java b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByWithValueFilterDataSet.java
index 2d136da..a02b662 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByWithValueFilterDataSet.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByWithValueFilterDataSet.java
@@ -125,7 +125,7 @@ public class GroupByWithValueFilterDataSet extends GroupByEngineDataSet {
public RowRecord nextWithoutConstraint() throws IOException {
if (!hasCachedTimeInterval) {
throw new IOException(
- "need to call hasNext() before calling next()" + " in GroupByWithoutValueFilterDataSet.");
+ "need to call hasNext() before calling next()" + " in GroupByWithValueFilterDataSet.");
}
hasCachedTimeInterval = false;
curAggregateResults = new AggregateResult[paths.size()];
diff --git a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByWithoutValueFilterDataSet.java b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByWithoutValueFilterDataSet.java
index 29a9948..3ead5da 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByWithoutValueFilterDataSet.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByWithoutValueFilterDataSet.java
@@ -54,7 +54,7 @@ public class GroupByWithoutValueFilterDataSet extends GroupByEngineDataSet {
private static final Logger logger =
LoggerFactory.getLogger(GroupByWithoutValueFilterDataSet.class);
- private Map<PartialPath, GroupByExecutor> pathExecutors = new HashMap<>();
+ protected Map<PartialPath, GroupByExecutor> pathExecutors = new HashMap<>();
/**
* path -> result index for each aggregation
@@ -65,7 +65,7 @@ public class GroupByWithoutValueFilterDataSet extends GroupByEngineDataSet {
*
* <p>s1 -> 0, 2 s2 -> 1
*/
- private Map<PartialPath, List<Integer>> resultIndexes = new HashMap<>();
+ protected Map<PartialPath, List<Integer>> resultIndexes = new HashMap<>();
public GroupByWithoutValueFilterDataSet() {}
diff --git a/server/src/main/java/org/apache/iotdb/db/query/executor/QueryRouter.java b/server/src/main/java/org/apache/iotdb/db/query/executor/QueryRouter.java
index 00e23b0..2828f34 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/executor/QueryRouter.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/executor/QueryRouter.java
@@ -32,7 +32,7 @@ import org.apache.iotdb.db.qp.physical.crud.UDTFPlan;
import org.apache.iotdb.db.query.context.QueryContext;
import org.apache.iotdb.db.query.control.SessionManager;
import org.apache.iotdb.db.query.dataset.groupby.GroupByEngineDataSet;
-import org.apache.iotdb.db.query.dataset.groupby.GroupByFillDataSet;
+import org.apache.iotdb.db.query.dataset.groupby.GroupByFillWithoutValueFilterDataSet;
import org.apache.iotdb.db.query.dataset.groupby.GroupByLevelDataSet;
import org.apache.iotdb.db.query.dataset.groupby.GroupByWithValueFilterDataSet;
import org.apache.iotdb.db.query.dataset.groupby.GroupByWithoutValueFilterDataSet;
@@ -159,6 +159,22 @@ public class QueryRouter implements IQueryRouter {
return new AggregationExecutor(context, aggregationPlan);
}
+ private IExpression getOptimizeExpression(GroupByTimePlan groupByTimePlan)
+ throws QueryFilterOptimizationException, QueryProcessException {
+ IExpression expression = groupByTimePlan.getExpression();
+ List<PartialPath> selectedSeries = groupByTimePlan.getDeduplicatedPaths();
+ GlobalTimeExpression timeExpression = getTimeExpression(groupByTimePlan);
+
+ if (expression == null) {
+ expression = timeExpression;
+ } else {
+ expression = BinaryExpression.and(expression, timeExpression);
+ }
+
+ // optimize expression to an executable one
+ return ExpressionOptimizer.getInstance().optimize(expression, new ArrayList<>(selectedSeries));
+ }
+
@Override
public QueryDataSet groupBy(GroupByTimePlan groupByTimePlan, QueryContext context)
throws QueryFilterOptimizationException, StorageEngineException, QueryProcessException,
@@ -173,19 +189,7 @@ public class QueryRouter implements IQueryRouter {
}
GroupByEngineDataSet dataSet = null;
- IExpression expression = groupByTimePlan.getExpression();
- List<PartialPath> selectedSeries = groupByTimePlan.getDeduplicatedPaths();
- GlobalTimeExpression timeExpression = getTimeExpression(groupByTimePlan);
-
- if (expression == null) {
- expression = timeExpression;
- } else {
- expression = BinaryExpression.and(expression, timeExpression);
- }
-
- // optimize expression to an executable one
- IExpression optimizedExpression =
- ExpressionOptimizer.getInstance().optimize(expression, new ArrayList<>(selectedSeries));
+ IExpression optimizedExpression = getOptimizeExpression(groupByTimePlan);
groupByTimePlan.setExpression(optimizedExpression);
if (optimizedExpression.getType() == ExpressionType.GLOBAL_TIME) {
@@ -250,17 +254,22 @@ public class QueryRouter implements IQueryRouter {
@Override
public QueryDataSet groupByFill(GroupByTimeFillPlan groupByFillPlan, QueryContext context)
- throws QueryFilterOptimizationException, StorageEngineException, QueryProcessException,
- IOException {
- GroupByEngineDataSet groupByEngineDataSet =
- (GroupByEngineDataSet) groupBy(groupByFillPlan, context);
- return new GroupByFillDataSet(
- groupByFillPlan.getDeduplicatedPaths(),
- groupByFillPlan.getDeduplicatedDataTypes(),
- groupByEngineDataSet,
- groupByFillPlan.getFillType(),
- context,
- groupByFillPlan);
+ throws QueryFilterOptimizationException, StorageEngineException, QueryProcessException {
+
+ GroupByEngineDataSet dataSet;
+ IExpression optimizedExpression = getOptimizeExpression(groupByFillPlan);
+ groupByFillPlan.setExpression(optimizedExpression);
+
+ if (optimizedExpression.getType() == ExpressionType.GLOBAL_TIME) {
+ dataSet = new GroupByFillWithoutValueFilterDataSet(context, groupByFillPlan);
+ } else {
+ // dataSet = new GroupByFillWithValueFilterDataSet(context, groupByFillPlan);
+ throw new QueryProcessException("Group by fill doesn't support valueFilter yet.");
+ }
+
+ // TODO: support group by level in group by fill
+
+ return dataSet;
}
@Override
diff --git a/server/src/main/java/org/apache/iotdb/db/query/executor/fill/IFill.java b/server/src/main/java/org/apache/iotdb/db/query/executor/fill/IFill.java
index a8472a4..47c7094 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/executor/fill/IFill.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/executor/fill/IFill.java
@@ -23,20 +23,29 @@ import org.apache.iotdb.db.exception.StorageEngineException;
import org.apache.iotdb.db.exception.query.QueryProcessException;
import org.apache.iotdb.db.metadata.PartialPath;
import org.apache.iotdb.db.query.context.QueryContext;
+import org.apache.iotdb.db.query.control.SessionManager;
+import org.apache.iotdb.db.query.dataset.groupby.GroupByEngineDataSet;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.read.TimeValuePair;
import java.io.IOException;
+import java.util.Calendar;
import java.util.Set;
public abstract class IFill {
- protected long queryTime;
+ protected long queryStartTime;
+ protected long queryEndTime;
protected TSDataType dataType;
- public IFill(TSDataType dataType, long queryTime) {
+ protected boolean isBeforeByMonth = false;
+ protected long beforeRange = 0;
+ protected boolean isAfterByMonth = false;
+ protected long afterRange = 0;
+
+ public IFill(TSDataType dataType, long queryStartTime) {
this.dataType = dataType;
- this.queryTime = queryTime;
+ this.queryStartTime = queryStartTime;
}
public IFill() {}
@@ -61,13 +70,73 @@ public abstract class IFill {
this.dataType = dataType;
}
- public void setQueryTime(long queryTime) {
- this.queryTime = queryTime;
+ public void setQueryStartTime(long queryStartTime) {
+ this.queryStartTime = queryStartTime;
+ }
+
+ public long getQueryStartTime() {
+ return queryStartTime;
}
- public long getQueryTime() {
- return queryTime;
+ public long getQueryEndTime() {
+ return queryEndTime;
}
abstract void constructFilter();
+
+ public boolean insideBeforeRange(long previous, long startTime) {
+ if (isBeforeByMonth) {
+ return previous
+ >= slideMonth(startTime, (int) (-beforeRange / GroupByEngineDataSet.MS_TO_MONTH));
+ } else {
+ return previous >= startTime - beforeRange;
+ }
+ }
+
+ public boolean insideAfterRange(long next, long startTime) {
+ if (isAfterByMonth) {
+ return next <= slideMonth(startTime, (int) (afterRange / GroupByEngineDataSet.MS_TO_MONTH));
+ } else {
+ return next <= startTime + afterRange;
+ }
+ }
+
+ public void convertRange(long startTime, long endTime) {
+ if (isBeforeByMonth) {
+ queryStartTime =
+ slideMonth(startTime, (int) (-beforeRange / GroupByEngineDataSet.MS_TO_MONTH));
+ } else {
+ queryStartTime = startTime - beforeRange;
+ }
+
+ if (isAfterByMonth) {
+ queryEndTime = slideMonth(endTime, (int) (afterRange / GroupByEngineDataSet.MS_TO_MONTH));
+ } else {
+ queryEndTime = endTime + afterRange;
+ }
+ }
+
+ public long getBeforeRange() {
+ return beforeRange;
+ }
+
+ public void setBeforeRange(long beforeRange) {
+ this.beforeRange = beforeRange;
+ }
+
+ public long getAfterRange() {
+ return afterRange;
+ }
+
+ public void setAfterRange(long afterRange) {
+ this.afterRange = afterRange;
+ }
+
+ protected long slideMonth(long startTime, int monthNum) {
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTimeZone(SessionManager.getInstance().getCurrSessionTimeZone());
+ calendar.setTimeInMillis(startTime);
+ calendar.add(Calendar.MONTH, monthNum);
+ return calendar.getTimeInMillis();
+ }
}
diff --git a/server/src/main/java/org/apache/iotdb/db/query/executor/fill/LinearFill.java b/server/src/main/java/org/apache/iotdb/db/query/executor/fill/LinearFill.java
index 4c4b783..5dc293f 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/executor/fill/LinearFill.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/executor/fill/LinearFill.java
@@ -24,6 +24,7 @@ import org.apache.iotdb.db.exception.StorageEngineException;
import org.apache.iotdb.db.exception.query.QueryProcessException;
import org.apache.iotdb.db.exception.query.UnSupportedFillTypeException;
import org.apache.iotdb.db.metadata.PartialPath;
+import org.apache.iotdb.db.qp.utils.DatetimeUtils;
import org.apache.iotdb.db.query.aggregation.AggregateResult;
import org.apache.iotdb.db.query.aggregation.impl.FirstValueAggrResult;
import org.apache.iotdb.db.query.aggregation.impl.MinTimeAggrResult;
@@ -45,8 +46,6 @@ import java.util.Set;
public class LinearFill extends IFill {
protected PartialPath seriesPath;
- protected long beforeRange;
- protected long afterRange;
protected Filter beforeFilter;
protected Filter afterFilter;
protected QueryContext context;
@@ -58,6 +57,17 @@ public class LinearFill extends IFill {
this.afterRange = afterRange;
}
+ public LinearFill(String beforeStr, String afterStr) {
+ this.beforeRange = DatetimeUtils.convertDurationStrToLong(beforeStr);
+ this.afterRange = DatetimeUtils.convertDurationStrToLong(afterStr);
+ if (beforeStr.toLowerCase().contains("mo")) {
+ this.isBeforeByMonth = true;
+ }
+ if (afterStr.toLowerCase().contains("mo")) {
+ this.isAfterByMonth = true;
+ }
+ }
+
/** Constructor of LinearFill. */
public LinearFill(TSDataType dataType, long queryTime, long beforeRange, long afterRange) {
super(dataType, queryTime);
@@ -65,25 +75,26 @@ public class LinearFill extends IFill {
this.afterRange = afterRange;
}
- public long getBeforeRange() {
- return beforeRange;
- }
-
- public void setBeforeRange(long beforeRange) {
+ public LinearFill(
+ TSDataType dataType,
+ long queryTime,
+ long beforeRange,
+ long afterRange,
+ boolean isBeforeByMonth,
+ boolean isAfterByMonth) {
+ super(dataType, queryTime);
this.beforeRange = beforeRange;
- }
-
- public long getAfterRange() {
- return afterRange;
- }
-
- public void setAfterRange(long afterRange) {
this.afterRange = afterRange;
+ this.isBeforeByMonth = isBeforeByMonth;
+ this.isAfterByMonth = isAfterByMonth;
}
+ public LinearFill() {}
+
@Override
public IFill copy() {
- return new LinearFill(dataType, queryTime, beforeRange, afterRange);
+ return new LinearFill(
+ dataType, queryStartTime, beforeRange, afterRange, isBeforeByMonth, isAfterByMonth);
}
@Override
@@ -91,14 +102,14 @@ public class LinearFill extends IFill {
Filter lowerBound =
beforeRange == -1
? TimeFilter.gtEq(Long.MIN_VALUE)
- : TimeFilter.gtEq(queryTime - beforeRange);
+ : TimeFilter.gtEq(queryStartTime - beforeRange);
Filter upperBound =
afterRange == -1
? TimeFilter.ltEq(Long.MAX_VALUE)
- : TimeFilter.ltEq(queryTime + afterRange);
+ : TimeFilter.ltEq(queryStartTime + afterRange);
// [queryTIme - beforeRange, queryTime + afterRange]
- beforeFilter = FilterFactory.and(lowerBound, TimeFilter.ltEq(queryTime));
- afterFilter = FilterFactory.and(TimeFilter.gtEq(queryTime), upperBound);
+ beforeFilter = FilterFactory.and(lowerBound, TimeFilter.ltEq(queryStartTime));
+ afterFilter = FilterFactory.and(TimeFilter.gtEq(queryStartTime), upperBound);
}
@Override
@@ -110,7 +121,7 @@ public class LinearFill extends IFill {
QueryContext context) {
this.seriesPath = path;
this.dataType = dataType;
- this.queryTime = queryTime;
+ this.queryStartTime = queryTime;
this.context = context;
this.deviceMeasurements = sensors;
constructFilter();
@@ -124,16 +135,16 @@ public class LinearFill extends IFill {
TimeValuePair afterPair = calculateSucceedingPoint();
// no before data or has data on the query timestamp
- if (beforePair.getValue() == null || beforePair.getTimestamp() == queryTime) {
- beforePair.setTimestamp(queryTime);
+ if (beforePair.getValue() == null || beforePair.getTimestamp() == queryStartTime) {
+ beforePair.setTimestamp(queryStartTime);
return beforePair;
}
// on after data or after data is out of range
if (afterPair.getValue() == null
- || afterPair.getTimestamp() < queryTime
- || (afterRange != -1 && afterPair.getTimestamp() > queryTime + afterRange)) {
- return new TimeValuePair(queryTime, null);
+ || afterPair.getTimestamp() < queryStartTime
+ || (afterRange != -1 && afterPair.getTimestamp() > queryStartTime + afterRange)) {
+ return new TimeValuePair(queryStartTime, null);
}
return average(beforePair, afterPair);
@@ -145,7 +156,13 @@ public class LinearFill extends IFill {
QueryResourceManager.getInstance().getQueryDataSource(seriesPath, context, beforeFilter);
LastPointReader lastReader =
new LastPointReader(
- seriesPath, dataType, deviceMeasurements, context, dataSource, queryTime, beforeFilter);
+ seriesPath,
+ dataType,
+ deviceMeasurements,
+ context,
+ dataSource,
+ queryStartTime,
+ beforeFilter);
return lastReader.readLastPoint();
}
@@ -189,7 +206,7 @@ public class LinearFill extends IFill {
private TimeValuePair average(TimeValuePair beforePair, TimeValuePair afterPair)
throws UnSupportedFillTypeException {
double totalTimeLength = (double) afterPair.getTimestamp() - beforePair.getTimestamp();
- double beforeTimeLength = (double) (queryTime - beforePair.getTimestamp());
+ double beforeTimeLength = (double) (queryStartTime - beforePair.getTimestamp());
switch (dataType) {
case INT32:
int startIntValue = beforePair.getValue().getInt();
@@ -228,7 +245,15 @@ public class LinearFill extends IFill {
default:
throw new UnSupportedFillTypeException(dataType);
}
- beforePair.setTimestamp(queryTime);
+ beforePair.setTimestamp(queryStartTime);
return beforePair;
}
+
+ public TimeValuePair averageWithTimeAndDataType(
+ TimeValuePair beforePair, TimeValuePair afterPair, long queryTime, TSDataType tsDataType)
+ throws UnSupportedFillTypeException {
+ this.queryStartTime = queryTime;
+ this.dataType = tsDataType;
+ return average(beforePair, afterPair);
+ }
}
diff --git a/server/src/main/java/org/apache/iotdb/db/query/executor/fill/PreviousFill.java b/server/src/main/java/org/apache/iotdb/db/query/executor/fill/PreviousFill.java
index c6a9916..c8a1842 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/executor/fill/PreviousFill.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/executor/fill/PreviousFill.java
@@ -22,6 +22,7 @@ import org.apache.iotdb.db.engine.querycontext.QueryDataSource;
import org.apache.iotdb.db.exception.StorageEngineException;
import org.apache.iotdb.db.exception.query.QueryProcessException;
import org.apache.iotdb.db.metadata.PartialPath;
+import org.apache.iotdb.db.qp.utils.DatetimeUtils;
import org.apache.iotdb.db.query.context.QueryContext;
import org.apache.iotdb.db.query.control.QueryResourceManager;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
@@ -37,34 +38,51 @@ public class PreviousFill extends IFill {
private PartialPath seriesPath;
private QueryContext context;
- private long beforeRange;
private Set<String> allSensors;
private Filter timeFilter;
private boolean untilLast;
public PreviousFill(TSDataType dataType, long queryTime, long beforeRange) {
- this(dataType, queryTime, beforeRange, false);
+ this(dataType, queryTime, beforeRange, false, false);
}
public PreviousFill(long beforeRange) {
this(beforeRange, false);
}
+ public PreviousFill(String beforeStr) {
+ this(beforeStr, false);
+ }
+
public PreviousFill(long beforeRange, boolean untilLast) {
this.beforeRange = beforeRange;
this.untilLast = untilLast;
}
- public PreviousFill(TSDataType dataType, long queryTime, long beforeRange, boolean untilLast) {
- super(dataType, queryTime);
+ public PreviousFill(String beforeStr, boolean untilLast) {
+ this.beforeRange = DatetimeUtils.convertDurationStrToLong(beforeStr);
+ this.untilLast = untilLast;
+ if (beforeStr.toLowerCase().contains("mo")) {
+ this.isBeforeByMonth = true;
+ }
+ }
+
+ public PreviousFill(
+ TSDataType dataType,
+ long queryStartTime,
+ long beforeRange,
+ boolean untilLast,
+ boolean isBeforeByMonth) {
+ super(dataType, queryStartTime);
this.beforeRange = beforeRange;
this.untilLast = untilLast;
+ this.isBeforeByMonth = isBeforeByMonth;
}
@Override
public IFill copy() {
- return new PreviousFill(dataType, queryTime, beforeRange, untilLast);
+ return new PreviousFill(dataType, queryStartTime, beforeRange, untilLast, isBeforeByMonth);
}
@Override
@@ -72,13 +90,9 @@ public class PreviousFill extends IFill {
Filter lowerBound =
beforeRange == -1
? TimeFilter.gtEq(Long.MIN_VALUE)
- : TimeFilter.gtEq(queryTime - beforeRange);
+ : TimeFilter.gtEq(queryStartTime - beforeRange);
// time in [queryTime - beforeRange, queryTime]
- timeFilter = FilterFactory.and(lowerBound, TimeFilter.ltEq(queryTime));
- }
-
- public long getBeforeRange() {
- return beforeRange;
+ timeFilter = FilterFactory.and(lowerBound, TimeFilter.ltEq(queryStartTime));
}
@Override
@@ -91,7 +105,7 @@ public class PreviousFill extends IFill {
this.seriesPath = path;
this.dataType = dataType;
this.context = context;
- this.queryTime = queryTime;
+ this.queryStartTime = queryTime;
this.allSensors = sensors;
constructFilter();
}
@@ -105,7 +119,7 @@ public class PreviousFill extends IFill {
timeFilter = dataSource.updateFilterUsingTTL(timeFilter);
LastPointReader lastReader =
new LastPointReader(
- seriesPath, dataType, allSensors, context, dataSource, queryTime, timeFilter);
+ seriesPath, dataType, allSensors, context, dataSource, queryStartTime, timeFilter);
return lastReader.readLastPoint();
}
diff --git a/server/src/main/java/org/apache/iotdb/db/query/executor/fill/ValueFill.java b/server/src/main/java/org/apache/iotdb/db/query/executor/fill/ValueFill.java
index 356e21b..e5df3cc 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/executor/fill/ValueFill.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/executor/fill/ValueFill.java
@@ -62,7 +62,7 @@ public class ValueFill extends IFill implements Cloneable {
long queryTime,
Set<String> deviceMeasurements,
QueryContext context) {
- this.queryTime = queryTime;
+ this.queryStartTime = queryTime;
}
@Override
@@ -74,7 +74,7 @@ public class ValueFill extends IFill implements Cloneable {
case FLOAT:
case DOUBLE:
case TEXT:
- return new TimeValuePair(queryTime, tsPrimitiveType);
+ return new TimeValuePair(queryStartTime, tsPrimitiveType);
default:
throw new UnSupportedDataTypeException("Unsupported data type:" + dataType);
}
diff --git a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBGroupByFillIT.java b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBGroupByFillIT.java
index aaae8eb..d06315d 100644
--- a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBGroupByFillIT.java
+++ b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBGroupByFillIT.java
@@ -22,7 +22,6 @@ import org.apache.iotdb.db.conf.IoTDBDescriptor;
import org.apache.iotdb.db.qp.logical.crud.AggregationQueryOperator;
import org.apache.iotdb.db.utils.EnvironmentUtils;
import org.apache.iotdb.jdbc.Config;
-import org.apache.iotdb.jdbc.IoTDBSQLException;
import org.junit.After;
import org.junit.Assert;
@@ -34,8 +33,7 @@ import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
-import static org.apache.iotdb.db.constant.TestConstant.TIMESTAMP_STR;
-import static org.apache.iotdb.db.constant.TestConstant.last_value;
+import static org.apache.iotdb.db.constant.TestConstant.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -48,20 +46,26 @@ public class IoTDBGroupByFillIT {
"CREATE TIMESERIES root.ln.wf01.wt01.status WITH DATATYPE=BOOLEAN, ENCODING=PLAIN",
"CREATE TIMESERIES root.ln.wf01.wt01.temperature WITH DATATYPE=INT32, ENCODING=PLAIN",
"CREATE TIMESERIES root.ln.wf01.wt01.hardware WITH DATATYPE=DOUBLE, ENCODING=PLAIN",
- "INSERT INTO root.ln.wf01.wt01(timestamp,temperature,status, hardware) "
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status, hardware) "
+ "values(10, 21, false, 11.1)",
- "INSERT INTO root.ln.wf01.wt01(timestamp,temperature,status, hardware) "
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status, hardware) "
+ "values(12, 23, true, 22.3)",
- "INSERT INTO root.ln.wf01.wt01(timestamp,temperature,status, hardware) "
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status, hardware) "
+ "values(14, 25, false, 33.5)",
- "INSERT INTO root.ln.wf01.wt01(timestamp,temperature,status, hardware) "
- + "values(29, 26, false, 33.2)",
- "INSERT INTO root.ln.wf01.wt01(timestamp,temperature,status, hardware) "
- + "values(36, 29, false, 44.7)",
- "INSERT INTO root.ln.wf01.wt01(timestamp,temperature,status, hardware) "
- + "values(37, 30, false, 55.8)",
- "INSERT INTO root.ln.wf01.wt01(timestamp,temperature,status, hardware) "
- + "values(39, 40, false, 33.0)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status, hardware) "
+ + "values(23, 28, true, 34.9)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status, hardware) "
+ + "values(25, 23, false, 31.7)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status, hardware) "
+ + "values(33, 29, false, 44.6)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status, hardware) "
+ + "values(36, 24, true, 44.8)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status, hardware) "
+ + "values(48, 28, false, 54.6)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status, hardware) "
+ + "values(50, 30, true, 55.8)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status, hardware) "
+ + "values(66, 40, false, 33.0)",
"flush"
};
@@ -81,10 +85,1108 @@ public class IoTDBGroupByFillIT {
}
@Test
- public void previousTest1() {
+ public void previousLastValueTest() {
+ String[] retArray =
+ new String[] {"17,null", "22,23", "27,23", "32,24", "37,24", "42,24", "47,30", "52,30"};
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select last_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[previous])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select last_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[previous]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void previousFirstValueTest() {
+ String[] retArray =
+ new String[] {
+ "17,null", "22,34.9", "27,34.9", "32,44.6", "37,44.6", "42,44.6", "47,54.6", "52,54.6"
+ };
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select first_value(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[previous])");
+
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(first_value("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select first_value(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[previous]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(first_value("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void previousAvgTest() {
+ String[] retArray =
+ new String[] {
+ "17,null", "22,33.3", "27,33.3", "32,44.7", "37,44.7", "42,44.7", "47,55.2", "52,55.2"
+ };
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select avg(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[previous])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(avg("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select avg(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[previous]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(avg("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void previousCountTest() {
+ String[] retArray =
+ new String[] {"17,0", "22,2", "27,0", "32,2", "37,0", "42,0", "47,2", "52,0"};
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select count(status) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[previous])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(count("root.ln.wf01.wt01.status"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select count(status) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[previous]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(count("root.ln.wf01.wt01.status"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void previousMaxTimeTest() {
+ String[] retArray =
+ new String[] {"17,null", "22,25", "27,25", "32,36", "37,36", "42,36", "47,50", "52,50"};
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select max_time(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[previous])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(max_time("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select max_time(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[previous]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(max_time("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void previousMaxValueTest() {
+ String[] retArray =
+ new String[] {"17,null", "22,28", "27,28", "32,29", "37,29", "42,29", "47,30", "52,30"};
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select max_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[previous])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(max_value("root.ln.wf01.wt01.temperature"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select max_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[previous]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(max_value("root.ln.wf01.wt01.temperature"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void previousMinTimeTest() {
+ String[] retArray =
+ new String[] {"17,null", "22,23", "27,23", "32,33", "37,33", "42,33", "47,48", "52,48"};
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select min_time(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[previous])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(min_time("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select min_time(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[previous]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(min_time("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void previousMinValueTest() {
+ String[] retArray =
+ new String[] {"17,null", "22,23", "27,23", "32,24", "37,24", "42,24", "47,28", "52,28"};
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select min_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[previous])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(min_value("root.ln.wf01.wt01.temperature"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select min_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[previous]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(min_value("root.ln.wf01.wt01.temperature"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void previousSumTest() {
+ String[] retArray =
+ new String[] {
+ "17,null", "22,66.6", "27,66.6", "32,89.4", "37,89.4", "42,89.4", "47,110.4", "52,110.4"
+ };
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select sum(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[previous])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(sum("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select sum(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[previous]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(sum("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void previousUntilLastLastValueTest() {
+ String[] retArray =
+ new String[] {
+ "17,null", "22,false", "27,false", "32,true", "37,true", "42,true", "47,true", "52,null"
+ };
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select last_value(status) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(boolean[previousUntilLast])");
+
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(last_value("root.ln.wf01.wt01.status"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select last_value(status) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(boolean[previousUntilLast]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(last_value("root.ln.wf01.wt01.status"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void previousUntilLastFirstValueTest() {
+ String[] retArray =
+ new String[] {
+ "17,null", "22,34.9", "27,34.9", "32,44.6", "37,44.6", "42,44.6", "47,54.6", "52,null"
+ };
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select first_value(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[previousUntilLast])");
+
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(first_value("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select first_value(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[previousUntilLast]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(first_value("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void previousUntilLastAvgTest() {
+ String[] retArray =
+ new String[] {
+ "17,null", "22,33.3", "27,33.3", "32,44.7", "37,44.7", "42,44.7", "47,55.2", "52,null"
+ };
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select avg(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[previousUntilLast])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(avg("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select avg(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[previousUntilLast]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(avg("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void previousUntilLastCountTest() {
+ String[] retArray =
+ new String[] {"17,0", "22,2", "27,0", "32,2", "37,0", "42,0", "47,2", "52,0"};
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select count(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[previousUntilLast])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(count("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select count(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[previousUntilLast]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(count("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void previousUntilLastMaxTimeTest() {
+ String[] retArray =
+ new String[] {"17,null", "22,25", "27,25", "32,36", "37,36", "42,36", "47,50", "52,null"};
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select max_time(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[previousUntilLast])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(max_time("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select max_time(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[previousUntilLast]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(max_time("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void previousUntilLastMaxValueTest() {
+ String[] retArray =
+ new String[] {"17,null", "22,28", "27,28", "32,29", "37,29", "42,29", "47,30", "52,null"};
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select max_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[previousUntilLast])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(max_value("root.ln.wf01.wt01.temperature"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select max_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[previousUntilLast]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(max_value("root.ln.wf01.wt01.temperature"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void previousUntilLastMinTimeTest() {
+ String[] retArray =
+ new String[] {"17,null", "22,23", "27,23", "32,33", "37,33", "42,33", "47,48", "52,null"};
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select min_time(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[previousUntilLast])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(min_time("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select min_time(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[previousUntilLast]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(min_time("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void previousUntilLastMinValueTest() {
+ String[] retArray =
+ new String[] {"17,null", "22,23", "27,23", "32,24", "37,24", "42,24", "47,28", "52,null"};
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select min_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[previousUntilLast])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(min_value("root.ln.wf01.wt01.temperature"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select min_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[previousUntilLast]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(min_value("root.ln.wf01.wt01.temperature"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void previousUntilLastSumTest() {
+ String[] retArray =
+ new String[] {
+ "17,null", "22,66.6", "27,66.6", "32,89.4", "37,89.4", "42,89.4", "47,110.4", "52,null"
+ };
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select sum(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[previousUntilLast])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(sum("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select sum(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[previousUntilLast]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(sum("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void usingLimit() {
+
+ String[] retArray = new String[] {"27,23", "32,24", "37,24", "42,24", "47,30"};
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select last_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[previous]) "
+ + "limit 5 offset 2");
+
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void valueLastValueTest() {
+ String[] retArray =
+ new String[] {"17,100", "22,23", "27,100", "32,24", "37,100", "42,100", "47,30", "52,100"};
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select last_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[100])");
+
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select last_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[100]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void valueFirstValueTest() {
+ String[] retArray =
+ new String[] {
+ "17,2.33", "22,34.9", "27,2.33", "32,44.6", "37,2.33", "42,2.33", "47,54.6", "52,2.33"
+ };
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select first_value(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[2.33])");
+
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(first_value("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select first_value(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[2.33]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(first_value("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void valueAvgTest() {
String[] retArray =
new String[] {
- "17,25", "22,25", "27,26", "32,29", "37,40", "42,40", "47,40",
+ "17,66.6", "22,33.3", "27,66.6", "32,44.7", "37,66.6", "42,66.6", "47,55.2", "52,66.6"
};
try (Connection connection =
@@ -92,9 +1194,113 @@ public class IoTDBGroupByFillIT {
Statement statement = connection.createStatement()) {
boolean hasResultSet =
statement.execute(
- "select last_value(temperature) from root.ln.wf01.wt01 "
- + "GROUP BY ([17, 48), 5ms) FILL(int32[previous])");
-
+ "select avg(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[66.6])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(avg("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select avg(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[66.6]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(avg("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void valueCountTest() {
+ String[] retArray =
+ new String[] {"17,0", "22,2", "27,0", "32,2", "37,0", "42,0", "47,2", "52,0"};
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select count(status) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[10])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(count("root.ln.wf01.wt01.status"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select count(status) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[10]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(count("root.ln.wf01.wt01.status"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void valueMaxTimeTest() {
+ String[] retArray =
+ new String[] {"17,888", "22,25", "27,888", "32,36", "37,888", "42,888", "47,50", "52,888"};
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select max_time(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[888])");
assertTrue(hasResultSet);
int cnt;
try (ResultSet resultSet = statement.getResultSet()) {
@@ -103,7 +1309,7 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"));
+ + resultSet.getString(max_time("root.ln.wf01.wt01.hardware"));
assertEquals(retArray[cnt], ans);
cnt++;
}
@@ -112,9 +1318,9 @@ public class IoTDBGroupByFillIT {
hasResultSet =
statement.execute(
- "select last_value(temperature) from root.ln.wf01.wt01 "
- + "GROUP BY ([17, 48), 5ms) FILL(int32[previous]) order by time desc");
-
+ "select max_time(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[888]) order by time desc");
assertTrue(hasResultSet);
try (ResultSet resultSet = statement.getResultSet()) {
cnt = 0;
@@ -122,13 +1328,12 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"));
+ + resultSet.getString(max_time("root.ln.wf01.wt01.hardware"));
assertEquals(retArray[retArray.length - cnt - 1], ans);
cnt++;
}
assertEquals(retArray.length, cnt);
}
-
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
@@ -136,28 +1341,103 @@ public class IoTDBGroupByFillIT {
}
@Test
- public void previousTest2() {
+ public void valueMaxValueTest() {
+ String[] retArray =
+ new String[] {"17,100", "22,28", "27,100", "32,29", "37,100", "42,100", "47,30", "52,100"};
+
try (Connection connection =
DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
Statement statement = connection.createStatement()) {
- statement.execute(
- "select count(temperature) from root.ln.wf01.wt01 "
- + "GROUP BY ([17, 48), 5ms) FILL(int32[previous])");
- } catch (IoTDBSQLException e) {
- assertTrue(e.getMessage().contains("Group By Fill only support last_value function"));
+ boolean hasResultSet =
+ statement.execute(
+ "select max_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[100])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(max_value("root.ln.wf01.wt01.temperature"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select max_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[100]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(max_value("root.ln.wf01.wt01.temperature"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
+ }
+
+ @Test
+ public void valueMinTimeTest() {
+ String[] retArray =
+ new String[] {"17,1", "22,23", "27,1", "32,33", "37,1", "42,1", "47,48", "52,1"};
try (Connection connection =
DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
Statement statement = connection.createStatement()) {
- statement.execute(
- "select count(temperature) from root.ln.wf01.wt01 "
- + "GROUP BY ([17, 48), 5ms) FILL(int32[previous]) order by time desc");
- } catch (IoTDBSQLException e) {
- assertTrue(e.getMessage().contains("Group By Fill only support last_value function"));
+ boolean hasResultSet =
+ statement.execute(
+ "select min_time(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[1])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(min_time("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select min_time(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[1]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(min_time("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
@@ -165,20 +1445,18 @@ public class IoTDBGroupByFillIT {
}
@Test
- public void previousTest3() {
+ public void valueMinValueTest() {
String[] retArray =
- new String[] {
- "2,null", "7,21", "12,25", "17,25", "22,25", "27,26", "32,29", "37,40", "42,40", "47,40",
- };
+ new String[] {"17,10", "22,23", "27,10", "32,24", "37,10", "42,10", "47,28", "52,10"};
try (Connection connection =
DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
Statement statement = connection.createStatement()) {
boolean hasResultSet =
statement.execute(
- "select last_value(temperature) from root.ln.wf01.wt01 "
- + "GROUP BY ([2, 48), 5ms) FILL(int32[previous])");
-
+ "select min_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[10])");
assertTrue(hasResultSet);
int cnt;
try (ResultSet resultSet = statement.getResultSet()) {
@@ -187,7 +1465,7 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"));
+ + resultSet.getString(min_value("root.ln.wf01.wt01.temperature"));
assertEquals(retArray[cnt], ans);
cnt++;
}
@@ -196,9 +1474,9 @@ public class IoTDBGroupByFillIT {
hasResultSet =
statement.execute(
- "select last_value(temperature) from root.ln.wf01.wt01 "
- + "GROUP BY ([2, 48), 5ms) FILL(int32[previous]) order by time desc");
-
+ "select min_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[10]) order by time desc");
assertTrue(hasResultSet);
try (ResultSet resultSet = statement.getResultSet()) {
cnt = 0;
@@ -206,13 +1484,12 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"));
+ + resultSet.getString(min_value("root.ln.wf01.wt01.temperature"));
assertEquals(retArray[retArray.length - cnt - 1], ans);
cnt++;
}
assertEquals(retArray.length, cnt);
}
-
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
@@ -220,19 +1497,17 @@ public class IoTDBGroupByFillIT {
}
@Test
- public void previousTest4() {
+ public void valueSumTest() {
String[] retArray =
new String[] {
- "2,null,null",
- "7,21,11.1",
- "12,25,33.5",
- "17,25,33.5",
- "22,25,33.5",
- "27,26,33.2",
- "32,29,44.7",
- "37,40,33.0",
- "42,40,33.0",
- "47,40,33.0",
+ "17,233.0",
+ "22,66.6",
+ "27,233.0",
+ "32,89.4",
+ "37,233.0",
+ "42,233.0",
+ "47,110.4",
+ "52,233.0"
};
try (Connection connection =
@@ -240,9 +1515,9 @@ public class IoTDBGroupByFillIT {
Statement statement = connection.createStatement()) {
boolean hasResultSet =
statement.execute(
- "select last_value(temperature), last_value(hardware) from root.ln.wf01.wt01 "
- + "GROUP BY ([2, 48), 5ms) FILL(int32[previous], double[previous])");
-
+ "select sum(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[233.0])");
assertTrue(hasResultSet);
int cnt;
try (ResultSet resultSet = statement.getResultSet()) {
@@ -251,9 +1526,7 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"))
- + ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.hardware"));
+ + resultSet.getString(sum("root.ln.wf01.wt01.hardware"));
assertEquals(retArray[cnt], ans);
cnt++;
}
@@ -262,9 +1535,9 @@ public class IoTDBGroupByFillIT {
hasResultSet =
statement.execute(
- "select last_value(temperature), last_value(hardware) from root.ln.wf01.wt01 "
- + "GROUP BY ([2, 48), 5ms) FILL(int32[previous], double[previous]) order by time desc");
-
+ "select sum(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[233.0]) order by time desc");
assertTrue(hasResultSet);
try (ResultSet resultSet = statement.getResultSet()) {
cnt = 0;
@@ -272,15 +1545,12 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"))
- + ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.hardware"));
+ + resultSet.getString(sum("root.ln.wf01.wt01.hardware"));
assertEquals(retArray[retArray.length - cnt - 1], ans);
cnt++;
}
assertEquals(retArray.length, cnt);
}
-
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
@@ -288,19 +1558,18 @@ public class IoTDBGroupByFillIT {
}
@Test
- public void leftORightCPreviousTest() {
+ public void linearLastValueTest() {
String[] retArray =
- new String[] {
- "10,21", "15,25", "20,25", "25,25", "30,26", "35,26", "40,40",
- };
+ new String[] {"17,null", "22,23", "27,23", "32,24", "37,26", "42,28", "47,30", "52,null"};
try (Connection connection =
DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
Statement statement = connection.createStatement()) {
boolean hasResultSet =
statement.execute(
- "select last_value(temperature) from root.ln.wf01.wt01 "
- + "GROUP BY ((5, 40], 5ms) FILL(int32[previous])");
+ "select last_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[linear])");
assertTrue(hasResultSet);
int cnt;
@@ -319,9 +1588,9 @@ public class IoTDBGroupByFillIT {
hasResultSet =
statement.execute(
- "select last_value(temperature) from root.ln.wf01.wt01 "
- + "GROUP BY ((5, 40], 5ms) FILL(int32[previous]) order by time desc");
-
+ "select last_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[linear]) order by time desc");
assertTrue(hasResultSet);
try (ResultSet resultSet = statement.getResultSet()) {
cnt = 0;
@@ -342,19 +1611,17 @@ public class IoTDBGroupByFillIT {
}
@Test
- public void previousAllTest() {
+ public void linearFirstValueTest() {
String[] retArray =
new String[] {
- "2,null,null",
- "7,21,11.1",
- "12,25,33.5",
- "17,25,33.5",
- "22,25,33.5",
- "27,26,33.2",
- "32,29,44.7",
- "37,40,33.0",
- "42,40,33.0",
- "47,40,33.0",
+ "17,null",
+ "22,34.9",
+ "27,39.75",
+ "32,44.6",
+ "37,47.93333333333334",
+ "42,51.266666666666666",
+ "47,54.6",
+ "52,null"
};
try (Connection connection =
@@ -362,8 +1629,9 @@ public class IoTDBGroupByFillIT {
Statement statement = connection.createStatement()) {
boolean hasResultSet =
statement.execute(
- "select last_value(temperature), last_value(hardware) from root.ln.wf01.wt01 "
- + "GROUP BY ([2, 48), 5ms) FILL(ALL[previous])");
+ "select first_value(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[linear])");
assertTrue(hasResultSet);
int cnt;
@@ -373,9 +1641,7 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"))
- + ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.hardware"));
+ + resultSet.getString(first_value("root.ln.wf01.wt01.hardware"));
assertEquals(retArray[cnt], ans);
cnt++;
}
@@ -384,9 +1650,9 @@ public class IoTDBGroupByFillIT {
hasResultSet =
statement.execute(
- "select last_value(temperature), last_value(hardware) from root.ln.wf01.wt01 "
- + "GROUP BY ([2, 48), 5ms) FILL(ALL[previous]) order by time desc");
-
+ "select first_value(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[linear]) order by time desc");
assertTrue(hasResultSet);
try (ResultSet resultSet = statement.getResultSet()) {
cnt = 0;
@@ -394,9 +1660,7 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"))
- + ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.hardware"));
+ + resultSet.getString(first_value("root.ln.wf01.wt01.hardware"));
assertEquals(retArray[retArray.length - cnt - 1], ans);
cnt++;
}
@@ -409,10 +1673,10 @@ public class IoTDBGroupByFillIT {
}
@Test
- public void previousUntilLastTest1() {
+ public void linearAvgTest() {
String[] retArray =
new String[] {
- "17,25", "22,25", "27,26", "32,29", "37,40", "42,null", "47,null",
+ "17,null", "22,33.3", "27,39.0", "32,44.7", "37,48.2", "42,51.7", "47,55.2", "52,null"
};
try (Connection connection =
@@ -420,9 +1684,9 @@ public class IoTDBGroupByFillIT {
Statement statement = connection.createStatement()) {
boolean hasResultSet =
statement.execute(
- "select last_value(temperature) from root.ln.wf01.wt01 "
- + "GROUP BY ([17, 48), 5ms) FILL(int32[previousUntilLast])");
-
+ "select avg(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[linear])");
assertTrue(hasResultSet);
int cnt;
try (ResultSet resultSet = statement.getResultSet()) {
@@ -431,17 +1695,18 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"));
+ + resultSet.getString(avg("root.ln.wf01.wt01.hardware"));
assertEquals(retArray[cnt], ans);
cnt++;
}
assertEquals(retArray.length, cnt);
}
+
hasResultSet =
statement.execute(
- "select last_value(temperature) from root.ln.wf01.wt01 "
- + "GROUP BY ([17, 48), 5ms) FILL(int32[previousUntilLast]) order by time desc");
-
+ "select avg(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[linear]) order by time desc");
assertTrue(hasResultSet);
try (ResultSet resultSet = statement.getResultSet()) {
cnt = 0;
@@ -449,7 +1714,7 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"));
+ + resultSet.getString(avg("root.ln.wf01.wt01.hardware"));
assertEquals(retArray[retArray.length - cnt - 1], ans);
cnt++;
}
@@ -462,30 +1727,103 @@ public class IoTDBGroupByFillIT {
}
@Test
- public void previousUntilLastTest2() {
+ public void linearCountTest() {
+ String[] retArray =
+ new String[] {"17,0", "22,2", "27,0", "32,2", "37,0", "42,0", "47,2", "52,0"};
+
try (Connection connection =
DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
Statement statement = connection.createStatement()) {
- statement.execute(
- "select count(temperature) from root.ln.wf01.wt01 "
- + "GROUP BY ([17, 48), 5ms) FILL(int32[previousUntilLast])");
- } catch (IoTDBSQLException e) {
- System.out.println(e.getMessage());
- assertTrue(e.getMessage().contains("Group By Fill only support last_value function"));
+ boolean hasResultSet =
+ statement.execute(
+ "select count(status) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[linear])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(count("root.ln.wf01.wt01.status"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select count(status) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[linear]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(count("root.ln.wf01.wt01.status"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
+ }
+
+ @Test
+ public void linearMaxTimeTest() {
+ String[] retArray =
+ new String[] {"17,null", "22,25", "27,30", "32,36", "37,40", "42,45", "47,50", "52,null"};
try (Connection connection =
DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
Statement statement = connection.createStatement()) {
- statement.execute(
- "select count(temperature) from root.ln.wf01.wt01 "
- + "GROUP BY ([17, 48), 5ms) FILL(int32[previousUntilLast]) order by time desc");
- } catch (IoTDBSQLException e) {
- System.out.println(e.getMessage());
- assertTrue(e.getMessage().contains("Group By Fill only support last_value function"));
+ boolean hasResultSet =
+ statement.execute(
+ "select max_time(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[linear])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(max_time("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select max_time(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[linear]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(max_time("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
@@ -493,21 +1831,18 @@ public class IoTDBGroupByFillIT {
}
@Test
- public void previousUntilLastTest3() {
+ public void linearMaxValueTest() {
String[] retArray =
- new String[] {
- "2,null", "7,21", "12,25", "17,25", "22,25", "27,26", "32,29", "37,40", "42,null",
- "47,null",
- };
+ new String[] {"17,null", "22,28", "27,28", "32,29", "37,29", "42,29", "47,30", "52,null"};
try (Connection connection =
DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
Statement statement = connection.createStatement()) {
boolean hasResultSet =
statement.execute(
- "select last_value(temperature) from root.ln.wf01.wt01 "
- + "GROUP BY ([2, 48), 5ms) FILL(int32[previousUntilLast])");
-
+ "select max_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[linear])");
assertTrue(hasResultSet);
int cnt;
try (ResultSet resultSet = statement.getResultSet()) {
@@ -516,7 +1851,7 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"));
+ + resultSet.getString(max_value("root.ln.wf01.wt01.temperature"));
assertEquals(retArray[cnt], ans);
cnt++;
}
@@ -525,9 +1860,9 @@ public class IoTDBGroupByFillIT {
hasResultSet =
statement.execute(
- "select last_value(temperature) from root.ln.wf01.wt01 "
- + "GROUP BY ([2, 48), 5ms) FILL(int32[previousUntilLast]) order by time desc");
-
+ "select max_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[linear]) order by time desc");
assertTrue(hasResultSet);
try (ResultSet resultSet = statement.getResultSet()) {
cnt = 0;
@@ -535,7 +1870,7 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"));
+ + resultSet.getString(max_value("root.ln.wf01.wt01.temperature"));
assertEquals(retArray[retArray.length - cnt - 1], ans);
cnt++;
}
@@ -548,29 +1883,18 @@ public class IoTDBGroupByFillIT {
}
@Test
- public void previousUntilLastTest4() {
+ public void linearMinTimeTest() {
String[] retArray =
- new String[] {
- "2,null,null",
- "7,21,11.1",
- "12,25,33.5",
- "17,25,33.5",
- "22,25,33.5",
- "27,26,33.2",
- "32,29,44.7",
- "37,40,33.0",
- "42,null,null",
- "47,null,null",
- };
+ new String[] {"17,null", "22,23", "27,28", "32,33", "37,38", "42,43", "47,48", "52,null"};
try (Connection connection =
DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
Statement statement = connection.createStatement()) {
boolean hasResultSet =
statement.execute(
- "select last_value(temperature), last_value(hardware) from root.ln.wf01.wt01 "
- + "GROUP BY ([2, 48), 5ms) FILL(int32[previousUntilLast], double[previousUntilLast])");
-
+ "select min_time(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[linear])");
assertTrue(hasResultSet);
int cnt;
try (ResultSet resultSet = statement.getResultSet()) {
@@ -579,9 +1903,7 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"))
- + ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.hardware"));
+ + resultSet.getString(min_time("root.ln.wf01.wt01.hardware"));
assertEquals(retArray[cnt], ans);
cnt++;
}
@@ -590,9 +1912,9 @@ public class IoTDBGroupByFillIT {
hasResultSet =
statement.execute(
- "select last_value(temperature), last_value(hardware) from root.ln.wf01.wt01 "
- + "GROUP BY ([2, 48), 5ms) FILL(int32[previousUntilLast], double[previousUntilLast]) order by time desc");
-
+ "select min_time(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int64[linear]) order by time desc");
assertTrue(hasResultSet);
try (ResultSet resultSet = statement.getResultSet()) {
cnt = 0;
@@ -600,9 +1922,7 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"))
- + ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.hardware"));
+ + resultSet.getString(min_time("root.ln.wf01.wt01.hardware"));
assertEquals(retArray[retArray.length - cnt - 1], ans);
cnt++;
}
@@ -615,20 +1935,18 @@ public class IoTDBGroupByFillIT {
}
@Test
- public void previousUntilLastTest5() {
+ public void linearMinValueTest() {
String[] retArray =
- new String[] {
- "17,25", "22,25", "27,26", "32,29", "37,40", "42,null", "47,null",
- };
+ new String[] {"17,null", "22,23", "27,23", "32,24", "37,25", "42,26", "47,28", "52,null"};
try (Connection connection =
DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
Statement statement = connection.createStatement()) {
boolean hasResultSet =
statement.execute(
- "select last_value(temperature) from root.ln.wf01.wt01 "
- + "GROUP BY ([17, 48), 5ms) FILL(float[previousUntilLast])");
-
+ "select min_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[linear])");
assertTrue(hasResultSet);
int cnt;
try (ResultSet resultSet = statement.getResultSet()) {
@@ -637,7 +1955,7 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"));
+ + resultSet.getString(min_value("root.ln.wf01.wt01.temperature"));
assertEquals(retArray[cnt], ans);
cnt++;
}
@@ -646,9 +1964,9 @@ public class IoTDBGroupByFillIT {
hasResultSet =
statement.execute(
- "select last_value(temperature) from root.ln.wf01.wt01 "
- + "GROUP BY ([17, 48), 5ms) FILL(float[previousUntilLast]) order by time desc");
-
+ "select min_value(temperature) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(int32[linear]) order by time desc");
assertTrue(hasResultSet);
try (ResultSet resultSet = statement.getResultSet()) {
cnt = 0;
@@ -656,13 +1974,12 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"));
+ + resultSet.getString(min_value("root.ln.wf01.wt01.temperature"));
assertEquals(retArray[retArray.length - cnt - 1], ans);
cnt++;
}
assertEquals(retArray.length, cnt);
}
-
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
@@ -670,18 +1987,20 @@ public class IoTDBGroupByFillIT {
}
@Test
- public void leftORightCPreviousUntilLastTest() {
+ public void linearSumTest() {
String[] retArray =
- new String[] {"9,null", "14,25", "19,25", "24,25", "29,26", "34,26", "39,40", "44,null"};
+ new String[] {
+ "17,null", "22,66.6", "27,78.0", "32,89.4", "37,96.4", "42,103.4", "47,110.4", "52,null"
+ };
try (Connection connection =
DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
Statement statement = connection.createStatement()) {
boolean hasResultSet =
statement.execute(
- "select last_value(temperature) from root.ln.wf01.wt01 "
- + "GROUP BY ((4, 44], 5ms) FILL(int32[previousUntilLast])");
-
+ "select sum(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[linear])");
assertTrue(hasResultSet);
int cnt;
try (ResultSet resultSet = statement.getResultSet()) {
@@ -690,13 +2009,31 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"));
+ + resultSet.getString(sum("root.ln.wf01.wt01.hardware"));
assertEquals(retArray[cnt], ans);
cnt++;
}
assertEquals(retArray.length, cnt);
}
+ hasResultSet =
+ statement.execute(
+ "select sum(hardware) from "
+ + "root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(double[linear]) order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(sum("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
@@ -704,19 +2041,10 @@ public class IoTDBGroupByFillIT {
}
@Test
- public void previousUntilLastAllTest() {
+ public void leftORightCPreviousTest() {
String[] retArray =
new String[] {
- "2,null,null",
- "7,21,11.1",
- "12,25,33.5",
- "17,25,33.5",
- "22,25,33.5",
- "27,26,33.2",
- "32,29,44.7",
- "37,40,33.0",
- "42,null,null",
- "47,null,null",
+ "10,21.0", "15,24.0", "20,24.0", "25,25.5", "30,25.5", "35,29.0", "40,24.0",
};
try (Connection connection =
@@ -724,8 +2052,8 @@ public class IoTDBGroupByFillIT {
Statement statement = connection.createStatement()) {
boolean hasResultSet =
statement.execute(
- "select last_value(temperature), last_value(hardware) from root.ln.wf01.wt01 "
- + "GROUP BY ([2, 48), 5ms) FILL(ALL[previousUntilLast])");
+ "select avg(temperature) from root.ln.wf01.wt01 "
+ + "GROUP BY ((5, 40], 5ms) FILL(double[previous])");
assertTrue(hasResultSet);
int cnt;
@@ -735,15 +2063,31 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"))
- + ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.hardware"));
+ + resultSet.getString(avg("root.ln.wf01.wt01.temperature"));
assertEquals(retArray[cnt], ans);
cnt++;
}
assertEquals(retArray.length, cnt);
}
+ hasResultSet =
+ statement.execute(
+ "select avg(temperature) from root.ln.wf01.wt01 "
+ + "GROUP BY ((5, 40], 5ms) FILL(double[previous]) order by time desc");
+
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(avg("root.ln.wf01.wt01.temperature"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
@@ -751,11 +2095,17 @@ public class IoTDBGroupByFillIT {
}
@Test
- public void usingLimit() {
-
+ public void previousAllTest() {
String[] retArray =
new String[] {
- "27,26", "32,29", "37,40", "42,40", "47,40",
+ "17,null,null",
+ "22,false,33.3",
+ "27,false,33.3",
+ "32,true,44.7",
+ "37,true,44.7",
+ "42,true,44.7",
+ "47,true,55.2",
+ "52,true,55.2"
};
try (Connection connection =
@@ -763,9 +2113,8 @@ public class IoTDBGroupByFillIT {
Statement statement = connection.createStatement()) {
boolean hasResultSet =
statement.execute(
- "select last_value(temperature) from root.ln.wf01.wt01 "
- + "GROUP BY ([17, 48), 5ms) FILL(int32[previous]) "
- + "limit 5 offset 2");
+ "select last_value(status), avg(hardware) from root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(ALL[previous])");
assertTrue(hasResultSet);
int cnt;
@@ -775,13 +2124,35 @@ public class IoTDBGroupByFillIT {
String ans =
resultSet.getString(TIMESTAMP_STR)
+ ","
- + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"));
+ + resultSet.getString(last_value("root.ln.wf01.wt01.status"))
+ + ","
+ + resultSet.getString(avg("root.ln.wf01.wt01.hardware"));
assertEquals(retArray[cnt], ans);
cnt++;
}
assertEquals(retArray.length, cnt);
}
+ hasResultSet =
+ statement.execute(
+ "select last_value(status), avg(hardware) from root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 55), 5ms) FILL(ALL[previous]) order by time desc");
+
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(last_value("root.ln.wf01.wt01.status"))
+ + ","
+ + resultSet.getString(avg("root.ln.wf01.wt01.hardware"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
diff --git a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBGroupByFillMixPathsIT.java b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBGroupByFillMixPathsIT.java
new file mode 100644
index 0000000..7068448
--- /dev/null
+++ b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBGroupByFillMixPathsIT.java
@@ -0,0 +1,294 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.iotdb.db.integration;
+
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.db.utils.EnvironmentUtils;
+import org.apache.iotdb.jdbc.Config;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+
+import static org.apache.iotdb.db.constant.TestConstant.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class IoTDBGroupByFillMixPathsIT {
+
+ private static String[] dataSet1 =
+ new String[] {
+ "SET STORAGE GROUP TO root.ln.wf01.wt01",
+ "CREATE TIMESERIES root.ln.wf01.wt01.temperature WITH DATATYPE=INT32, ENCODING=PLAIN",
+ "CREATE TIMESERIES root.ln.wf01.wt01.hardware WITH DATATYPE=DOUBLE, ENCODING=PLAIN",
+ "CREATE TIMESERIES root.ln.wf01.wt01.status WITH DATATYPE=BOOLEAN, ENCODING=PLAIN",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature) values(8, 23)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, status) values(10, true)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, hardware) values(11, 11.0)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature) values(23, 28)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature) values(25, 23)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, hardware) values(27, 33.7)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, hardware) values(29, 35.3)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, hardware) values(30, 36.0)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status, hardware) values(32, 22, false, 40.7)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status, hardware) values(33, 25, false, 42.5)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status, hardware) values(34, 29, false, 43.6)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status, hardware) values(35, 23, false, 41.8)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status, hardware) values(36, 27, true, 48.2)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, hardware) values(37, 36.8)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, hardware) values(40, 38.2)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, hardware) values(41, 36.0)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, status) values(44, false)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, status) values(45, false)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature) values(47, 35)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature) values(48, 42)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature) values(50, 36)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature) values(51, 22)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status) values(52, 15, false)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status) values(53, 13, true)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status) values(54, 24, false)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status) values(55, 38, false)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature, status) values(56, 20, true)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, hardware) values(58, 40.5)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, hardware) values(60, 27.5)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, hardware) values(61, 36.4)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, temperature) values(72, 33)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, status) values(74, true)",
+ "INSERT INTO root.ln.wf01.wt01(timestamp, hardware) values(75, 46.8)",
+ "flush"
+ };
+
+ @Before
+ public void setUp() throws Exception {
+ EnvironmentUtils.closeStatMonitor();
+ EnvironmentUtils.envSetUp();
+ IoTDBDescriptor.getInstance().getConfig().setPartitionInterval(1000);
+ Class.forName(Config.JDBC_DRIVER_NAME);
+ prepareData();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ IoTDBDescriptor.getInstance().getConfig().setPartitionInterval(86400);
+ EnvironmentUtils.cleanEnv();
+ }
+
+ private void prepareData() {
+ try (Connection connection =
+ DriverManager.getConnection(
+ Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+
+ for (String sql : dataSet1) {
+ statement.execute(sql);
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void singlePathMixTest() {
+ String[] retArray =
+ new String[] {
+ // "7,23.0,23,8"
+ "17,41.66666666666667,23,8",
+ "22,51.0,23,25",
+ "27,88.5,25,25",
+ "32,126.0,27,36",
+ "37,129.0,26,36",
+ "42,132.0,24,36",
+ "47,135.0,22,51",
+ "52,110.0,20,56",
+ "57,null,23,null",
+ "62,71.5,26,null"
+ // "72,33.0,33,72"
+ };
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select sum(temperature), last_value(temperature), max_time(temperature) "
+ + "from root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 65), 5ms) "
+ + "FILL(double[linear, 12ms, 12ms], int32[linear, 10ms, 18ms], int64[previousUntilLast, 17ms])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(sum("root.ln.wf01.wt01.temperature"))
+ + ","
+ + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"))
+ + ","
+ + resultSet.getString(max_time("root.ln.wf01.wt01.temperature"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select sum(temperature), last_value(temperature), max_time(temperature) "
+ + "from root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 65), 5ms) "
+ + "FILL(double[linear, 12ms, 12ms], int32[linear, 10ms, 18ms], int64[previousUntilLast, 17ms]) "
+ + "order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(sum("root.ln.wf01.wt01.temperature"))
+ + ","
+ + resultSet.getString(last_value("root.ln.wf01.wt01.temperature"))
+ + ","
+ + resultSet.getString(max_time("root.ln.wf01.wt01.temperature"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void MultiPathsMixTest() {
+ String[] retArray =
+ new String[] {
+ "17,41.66666666666667,23.0,10,23,23.5,true",
+ "22,51.0,null,10,23,null,true",
+ "27,88.5,35.0,null,23,36.0,true",
+ "32,126.0,43.36,36,22,48.2,false",
+ "37,129.0,37.0,36,22,38.2,true",
+ "42,132.0,null,45,22,null,false",
+ "47,135.0,35.900000000000006,45,22,39.35,true",
+ "52,110.0,null,56,13,null,false",
+ "57,null,34.800000000000004,null,18,40.5,true",
+ "62,71.5,38.800000000000004,null,23,42.6,true"
+ };
+
+ /* Format result
+ linear, linear, preUntil, linear, linear, value
+ 7, 23.0, 11.0, 10, 23, 11.0, true
+ 17, 41.67(null), 23.0(null), 10(null), 23(null), 23.5(null), true(null)
+ 22, 51.0, null, 10(null), 23, null, true(null)
+ 27, 88.5(null), 35.0, null, 23(null), 36.0, true(null)
+ 32, 126.0, 43.36, 36, 22, 48.2, false
+ 37, 129.0(null), 37.0, 36(null), 22(null), 38.2, true(null)
+ 42, 132.0(null), null, 45, 22(null), null, false
+ 47, 135.0, 35.9(null), 45(null), 22, 39.35(null), true(null)
+ 52, 110.0, null, 56, 13, null, false
+ 57, null, 34.8, null, 18(null), 40.5, true(null)
+ 62, 71.5(null), 38.8(null), null, 23(null), 42.6(null), true(null)
+ 72, 33.0, 46.8, 74, 33, 46.8, true
+ */
+
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+ boolean hasResultSet =
+ statement.execute(
+ "select sum(temperature), avg(hardware), max_time(status), "
+ + "min_value(temperature), max_value(hardware), first_value(status) "
+ + "from root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 65), 5ms) "
+ + "FILL(double[linear, 12ms, 12ms], int32[linear, 12ms, 18ms], "
+ + "int64[previousUntilLast, 17ms], boolean[true])");
+ assertTrue(hasResultSet);
+ int cnt;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(sum("root.ln.wf01.wt01.temperature"))
+ + ","
+ + resultSet.getString(avg("root.ln.wf01.wt01.hardware"))
+ + ","
+ + resultSet.getString(max_time("root.ln.wf01.wt01.status"))
+ + ","
+ + resultSet.getString(min_value("root.ln.wf01.wt01.temperature"))
+ + ","
+ + resultSet.getString(max_value("root.ln.wf01.wt01.hardware"))
+ + ","
+ + resultSet.getString(first_value("root.ln.wf01.wt01.status"));
+ assertEquals(retArray[cnt], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ hasResultSet =
+ statement.execute(
+ "select sum(temperature), avg(hardware), max_time(status), "
+ + "min_value(temperature), max_value(hardware), first_value(status) "
+ + "from root.ln.wf01.wt01 "
+ + "GROUP BY ([17, 65), 5ms) "
+ + "FILL(double[linear, 12ms, 12ms], int32[linear, 12ms, 18ms], "
+ + "int64[previousUntilLast, 17ms], boolean[true]) "
+ + "order by time desc");
+ assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(sum("root.ln.wf01.wt01.temperature"))
+ + ","
+ + resultSet.getString(avg("root.ln.wf01.wt01.hardware"))
+ + ","
+ + resultSet.getString(max_time("root.ln.wf01.wt01.status"))
+ + ","
+ + resultSet.getString(min_value("root.ln.wf01.wt01.temperature"))
+ + ","
+ + resultSet.getString(max_value("root.ln.wf01.wt01.hardware"))
+ + ","
+ + resultSet.getString(first_value("root.ln.wf01.wt01.status"));
+ assertEquals(retArray[retArray.length - cnt - 1], ans);
+ cnt++;
+ }
+ assertEquals(retArray.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+}
diff --git a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBGroupByMonthFillIT.java b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBGroupByMonthFillIT.java
new file mode 100644
index 0000000..a770460
--- /dev/null
+++ b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBGroupByMonthFillIT.java
@@ -0,0 +1,274 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.integration;
+
+import org.apache.iotdb.db.utils.EnvironmentUtils;
+import org.apache.iotdb.jdbc.Config;
+import org.apache.iotdb.jdbc.IoTDBConnection;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.TimeZone;
+
+import static org.apache.iotdb.db.constant.TestConstant.sum;
+import static org.junit.Assert.fail;
+
+public class IoTDBGroupByMonthFillIT {
+
+ private static final String TIMESTAMP_STR = "Time";
+ private final DateFormat df = new SimpleDateFormat("MM/dd/yyyy:HH:mm:ss");
+
+ @Before
+ public void setUp() throws Exception {
+ df.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
+ EnvironmentUtils.envSetUp();
+ Class.forName(Config.JDBC_DRIVER_NAME);
+ prepareData();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ EnvironmentUtils.cleanEnv();
+ }
+
+ /** Test StartTime: 2020-02-15, EndTime: 2020-11-15 PreviousFill beforeRange = 1mo */
+ @Test
+ public void previousFillTest1() {
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+
+ String[] retArray1 = {
+ "02/15/2020:02:00:00", "1.0",
+ "03/15/2020:02:00:00", "3.0",
+ "04/15/2020:02:00:00", "3.0",
+ "05/15/2020:02:00:00", null,
+ "06/15/2020:02:00:00", "6.0",
+ "07/15/2020:02:00:00", "6.0",
+ "08/15/2020:02:00:00", null,
+ "09/15/2020:02:00:00", "9.0",
+ "10/15/2020:02:00:00", "9.0",
+ "11/15/2020:02:00:00", null,
+ };
+
+ ((IoTDBConnection) connection).setTimeZone("GMT+00:00");
+ boolean hasResultSet =
+ statement.execute(
+ "select sum(temperature) from root.sg1.d1 "
+ + "GROUP BY ([1581732000000, 1607997600000), 1mo) "
+ + "FILL(ALL[previous, 1mo])");
+
+ Assert.assertTrue(hasResultSet);
+ int cnt = 0;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ while (resultSet.next()) {
+ String time = resultSet.getString(TIMESTAMP_STR);
+ String ans = resultSet.getString(sum("root.sg1.d1.temperature"));
+ Assert.assertEquals(retArray1[cnt++], df.format(Long.parseLong(time)));
+ Assert.assertEquals(retArray1[cnt++], ans);
+ }
+ Assert.assertEquals(retArray1.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ /** Test StartTime: 2020-02-15, EndTime: 2020-11-15 PreviousFill beforeRange = 2mo */
+ @Test
+ public void previousFillTest2() {
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+
+ String[] retArray1 = {
+ "02/15/2020:02:00:00", "1.0",
+ "03/15/2020:02:00:00", "3.0",
+ "04/15/2020:02:00:00", "3.0",
+ "05/15/2020:02:00:00", "3.0",
+ "06/15/2020:02:00:00", "6.0",
+ "07/15/2020:02:00:00", "6.0",
+ "08/15/2020:02:00:00", "6.0",
+ "09/15/2020:02:00:00", "9.0",
+ "10/15/2020:02:00:00", "9.0",
+ "11/15/2020:02:00:00", "9.0",
+ };
+
+ ((IoTDBConnection) connection).setTimeZone("GMT+00:00");
+ boolean hasResultSet =
+ statement.execute(
+ "select sum(temperature) from root.sg1.d1 "
+ + "GROUP BY ([1581732000000, 1607997600000), 1mo) "
+ + "FILL(ALL[previous, 2mo])");
+
+ Assert.assertTrue(hasResultSet);
+ int cnt = 0;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ while (resultSet.next()) {
+ String time = resultSet.getString(TIMESTAMP_STR);
+ String ans = resultSet.getString(sum("root.sg1.d1.temperature"));
+ Assert.assertEquals(retArray1[cnt++], df.format(Long.parseLong(time)));
+ Assert.assertEquals(retArray1[cnt++], ans);
+ }
+ Assert.assertEquals(retArray1.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ /**
+ * Test StartTime: 2020-02-15, EndTime: 2020-11-15 PreviousFill beforeRange = 1mo, afterRange =
+ * 1mo
+ */
+ @Test
+ public void LinearFillTest1() {
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+
+ String[] retArray1 = {
+ "02/15/2020:02:00:00", "2.0",
+ "03/15/2020:02:00:00", "3.0",
+ "04/15/2020:02:00:00", null,
+ "05/15/2020:02:00:00", null,
+ "06/15/2020:02:00:00", "6.0",
+ "07/15/2020:02:00:00", null,
+ "08/15/2020:02:00:00", null,
+ "09/15/2020:02:00:00", "9.0",
+ "10/15/2020:02:00:00", null,
+ "11/15/2020:02:00:00", null,
+ };
+
+ ((IoTDBConnection) connection).setTimeZone("GMT+00:00");
+ boolean hasResultSet =
+ statement.execute(
+ "select sum(temperature) from root.sg1.d1 "
+ + "GROUP BY ([1581732000000, 1607997600000), 1mo) "
+ + "FILL(ALL[linear, 1mo, 1mo])");
+
+ Assert.assertTrue(hasResultSet);
+ int cnt = 0;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ while (resultSet.next()) {
+ String time = resultSet.getString(TIMESTAMP_STR);
+ String ans = resultSet.getString(sum("root.sg1.d1.temperature"));
+ Assert.assertEquals(retArray1[cnt++], df.format(Long.parseLong(time)));
+ if (retArray1[cnt] == null) {
+ Assert.assertNull(ans);
+ } else {
+ Assert.assertEquals(Double.valueOf(retArray1[cnt]), Double.valueOf(ans), 0.1);
+ }
+ ++cnt;
+ }
+ Assert.assertEquals(retArray1.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ /**
+ * Test StartTime: 2020-02-15, EndTime: 2020-11-15 PreviousFill beforeRange = 2mo, afterRange =
+ * 2mo
+ */
+ @Test
+ public void LinearFillTest2() {
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+
+ String[] retArray1 = {
+ "02/15/2020:02:00:00", "2.0",
+ "03/15/2020:02:00:00", "3.0",
+ "04/15/2020:02:00:00", "4.0",
+ "05/15/2020:02:00:00", "5.0",
+ "06/15/2020:02:00:00", "6.0",
+ "07/15/2020:02:00:00", "7.0",
+ "08/15/2020:02:00:00", "8.0",
+ "09/15/2020:02:00:00", "9.0",
+ "10/15/2020:02:00:00", "10.0",
+ "11/15/2020:02:00:00", "11.0",
+ };
+
+ ((IoTDBConnection) connection).setTimeZone("GMT+00:00");
+ boolean hasResultSet =
+ statement.execute(
+ "select sum(temperature) from root.sg1.d1 "
+ + "GROUP BY ([1581732000000, 1607997600000), 1mo) "
+ + "FILL(ALL[linear, 2mo, 2mo])");
+
+ Assert.assertTrue(hasResultSet);
+ int cnt = 0;
+ try (ResultSet resultSet = statement.getResultSet()) {
+ while (resultSet.next()) {
+ String time = resultSet.getString(TIMESTAMP_STR);
+ String ans = resultSet.getString(sum("root.sg1.d1.temperature"));
+ Assert.assertEquals(retArray1[cnt++], df.format(Long.parseLong(time)));
+ Assert.assertEquals(Double.valueOf(retArray1[cnt++]), Double.valueOf(ans), 0.1);
+ }
+ Assert.assertEquals(retArray1.length, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ private void prepareData() {
+ try (Connection connection =
+ DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+
+ // 2020-01-15
+ statement.execute(
+ "insert into root.sg1.d1(timestamp, temperature) " + "values (1579053600000, 1)");
+ // 2020-03-16
+ statement.execute(
+ "insert into root.sg1.d1(timestamp, temperature) " + "values (1584324000000, 3)");
+ // 2020-06-17
+ statement.execute(
+ "insert into root.sg1.d1(timestamp, temperature) " + "values (1592359200000, 6)");
+ // 2020-09-18
+ statement.execute(
+ "insert into root.sg1.d1(timestamp, temperature) " + "values (1600394400000, 9)");
+ // 2020-12-19
+ statement.execute(
+ "insert into root.sg1.d1(timestamp, temperature) " + "values (1608343200000, 12)");
+
+ statement.execute("flush");
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/server/src/test/java/org/apache/iotdb/db/qp/physical/PhysicalPlanTest.java b/server/src/test/java/org/apache/iotdb/db/qp/physical/PhysicalPlanTest.java
index 1b6c5f7..1b95b3b 100644
--- a/server/src/test/java/org/apache/iotdb/db/qp/physical/PhysicalPlanTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/qp/physical/PhysicalPlanTest.java
@@ -73,7 +73,6 @@ import org.apache.iotdb.tsfile.read.filter.TimeFilter;
import org.apache.iotdb.tsfile.read.filter.ValueFilter;
import org.apache.iotdb.tsfile.read.filter.factory.FilterFactory;
-import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -359,37 +358,40 @@ public class PhysicalPlanTest {
}
}
- @Test
- public void testGroupByFill2() {
- String sqlStr =
- "select last_value(s1) "
- + " from root.vehicle.d1 "
- + "group by([8,737), 3ms) fill(ALL[previousuntillast])";
- try {
- PhysicalPlan plan = processor.parseSQLToPhysicalPlan(sqlStr);
- if (!plan.isQuery()) {
- fail();
- }
- if (!(plan instanceof GroupByTimeFillPlan)) {
- fail();
- }
- GroupByTimeFillPlan groupByFillPlan = (GroupByTimeFillPlan) plan;
- assertEquals(3L, groupByFillPlan.getInterval());
- assertEquals(3L, groupByFillPlan.getSlidingStep());
- assertEquals(8L, groupByFillPlan.getStartTime());
- assertEquals(737L, groupByFillPlan.getEndTime());
- assertEquals(TSDataType.values().length, groupByFillPlan.getFillType().size());
- for (TSDataType tsDataType : TSDataType.values()) {
- assertTrue(groupByFillPlan.getFillType().containsKey(tsDataType));
- assertTrue(groupByFillPlan.getFillType().get(tsDataType) instanceof PreviousFill);
- PreviousFill previousFill = (PreviousFill) groupByFillPlan.getFillType().get(tsDataType);
- assertTrue(previousFill.isUntilLast());
- }
- } catch (Exception e) {
- e.printStackTrace();
- fail();
- }
- }
+ // TODO: @CRZbulabula
+ // support VECTOR in group by fill
+ // @Test
+ // public void testGroupByFill2() {
+ // String sqlStr =
+ // "select last_value(s1) "
+ // + " from root.vehicle.d1 "
+ // + "group by([8,737), 3ms) fill(ALL[previousuntillast])";
+ // try {
+ // PhysicalPlan plan = processor.parseSQLToPhysicalPlan(sqlStr);
+ // if (!plan.isQuery()) {
+ // fail();
+ // }
+ // if (!(plan instanceof GroupByTimeFillPlan)) {
+ // fail();
+ // }
+ // GroupByTimeFillPlan groupByFillPlan = (GroupByTimeFillPlan) plan;
+ // assertEquals(3L, groupByFillPlan.getInterval());
+ // assertEquals(3L, groupByFillPlan.getSlidingStep());
+ // assertEquals(8L, groupByFillPlan.getStartTime());
+ // assertEquals(737L, groupByFillPlan.getEndTime());
+ // assertEquals(TSDataType.values().length, groupByFillPlan.getFillType().size());
+ // for (TSDataType tsDataType : TSDataType.values()) {
+ // assertTrue(groupByFillPlan.getFillType().containsKey(tsDataType));
+ // assertTrue(groupByFillPlan.getFillType().get(tsDataType) instanceof PreviousFill);
+ // PreviousFill previousFill = (PreviousFill)
+ // groupByFillPlan.getFillType().get(tsDataType);
+ // assertTrue(previousFill.isUntilLast());
+ // }
+ // } catch (Exception e) {
+ // e.printStackTrace();
+ // fail();
+ // }
+ // }
@Test
public void testGroupByFill3() {
@@ -434,12 +436,12 @@ public class PhysicalPlanTest {
String sqlStr =
"select last_value(d1.s1), last_value(d2.s1)"
+ " from root.vehicle "
- + "group by([8,737), 3ms) fill(int32[linear])";
+ + "group by([8,737), 3ms) fill(boolean[linear])";
try {
processor.parseSQLToPhysicalPlan(sqlStr);
fail();
} catch (SQLParserException e) {
- assertEquals("group by fill doesn't support linear fill", e.getMessage());
+ assertEquals("type BOOLEAN cannot use linear fill function", e.getMessage());
} catch (Exception e) {
e.printStackTrace();
fail();
@@ -451,12 +453,12 @@ public class PhysicalPlanTest {
String sqlStr =
"select last_value(d1.s1), count(d2.s1)"
+ " from root.vehicle "
- + "group by([8,737), 3ms) fill(int32[previous])";
+ + "group by([8,737), 3ms) fill(text[linear])";
try {
processor.parseSQLToPhysicalPlan(sqlStr);
fail();
- } catch (QueryProcessException e) {
- assertEquals("Group By Fill only support last_value function", e.getMessage());
+ } catch (SQLParserException e) {
+ assertEquals("type TEXT cannot use linear fill function", e.getMessage());
} catch (Exception e) {
e.printStackTrace();
fail();
@@ -466,23 +468,6 @@ public class PhysicalPlanTest {
@Test
public void testGroupByFill6() {
String sqlStr =
- "select count(s1)"
- + "from root.vehicle.d1 "
- + "group by([8,737), 3ms, 5ms) fill(int32[previous])";
- try {
- processor.parseSQLToPhysicalPlan(sqlStr);
- fail();
- } catch (ParseCancellationException e) {
- assertTrue(e.getMessage().contains("mismatched input 'fill'"));
- } catch (Exception e) {
- e.printStackTrace();
- fail();
- }
- }
-
- @Test
- public void testGroupByFill7() {
- String sqlStr =
"select last_value(d1.s1), last_value(d2.s1)"
+ " from root.vehicle "
+ "group by([8,737), 3ms) fill(int32[previousuntillast,10ms], int64[previous,10ms])";
diff --git a/server/src/test/java/org/apache/iotdb/db/query/dataset/groupby/GroupByFillDataSetTest.java b/server/src/test/java/org/apache/iotdb/db/query/dataset/groupby/GroupByFillDataSetTest.java
index 9e658e6..65d157b 100644
--- a/server/src/test/java/org/apache/iotdb/db/query/dataset/groupby/GroupByFillDataSetTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/query/dataset/groupby/GroupByFillDataSetTest.java
@@ -108,87 +108,93 @@ public class GroupByFillDataSetTest {
}
}
- @Test
- public void groupByWithValueFilterFillTest() throws Exception {
- QueryPlan queryPlan =
- (QueryPlan)
- processor.parseSQLToPhysicalPlan(
- "select last_value(s0) from root.vehicle.* where s1 > 1 group by ([0,20), 1ms) fill (int32[Previous]) order by time desc");
- QueryDataSet dataSet =
- queryExecutor.processQuery(queryPlan, EnvironmentUtils.TEST_QUERY_CONTEXT);
- for (int i = 19; i >= 7; i--) {
- assertTrue(dataSet.hasNext());
- assertEquals(i + "\t7", dataSet.next().toString());
- }
- assertTrue(dataSet.hasNext());
- assertEquals("6\t6", dataSet.next().toString());
- for (int i = 5; i >= 0; i--) {
- assertTrue(dataSet.hasNext());
- assertEquals(i + "\tnull", dataSet.next().toString());
- }
- }
-
- @Test
- public void groupByWithAndFilterFillTest() throws Exception {
- QueryPlan queryPlan =
- (QueryPlan)
- processor.parseSQLToPhysicalPlan(
- "select last_value(s0) from root.vehicle.* where s1 > 1 or s0 > 1 group by ([0,20), 1ms) fill (int32[Previous]) order by time desc");
- QueryDataSet dataSet =
- queryExecutor.processQuery(queryPlan, EnvironmentUtils.TEST_QUERY_CONTEXT);
- for (int i = 19; i >= 8; i--) {
- assertTrue(dataSet.hasNext());
- assertEquals(i + "\t8", dataSet.next().toString());
- }
- assertTrue(dataSet.hasNext());
- assertEquals("7\t7", dataSet.next().toString());
- assertTrue(dataSet.hasNext());
- assertEquals("6\t6", dataSet.next().toString());
- for (int i = 5; i >= 0; i--) {
- assertTrue(dataSet.hasNext());
- assertEquals(i + "\tnull", dataSet.next().toString());
- }
- }
+ // TODO: @CRZbulabula
+ // GroupByFillWithValueFilterDataSet
+ // @Test
+ // public void groupByWithValueFilterFillTest() throws Exception {
+ // QueryPlan queryPlan =
+ // (QueryPlan)
+ // processor.parseSQLToPhysicalPlan(
+ // "select last_value(s0) from root.vehicle.* where s1 > 1 group by ([0,20), 1ms)
+ // fill (int32[Previous]) order by time desc");
+ // QueryDataSet dataSet =
+ // queryExecutor.processQuery(queryPlan, EnvironmentUtils.TEST_QUERY_CONTEXT);
+ // for (int i = 19; i >= 7; i--) {
+ // assertTrue(dataSet.hasNext());
+ // assertEquals(i + "\t7", dataSet.next().toString());
+ // }
+ // assertTrue(dataSet.hasNext());
+ // assertEquals("6\t6", dataSet.next().toString());
+ // for (int i = 5; i >= 0; i--) {
+ // assertTrue(dataSet.hasNext());
+ // assertEquals(i + "\tnull", dataSet.next().toString());
+ // }
+ // }
- @Test
- public void groupByWithFirstNullTest() throws Exception {
- QueryPlan queryPlan =
- (QueryPlan)
- processor.parseSQLToPhysicalPlan(
- "select last_value(s0) from root.vehicle.* where s1 > 1 or s0 > 1 group by ([5,20), 1ms) fill (int32[Previous]) order by time desc");
- QueryDataSet dataSet =
- queryExecutor.processQuery(queryPlan, EnvironmentUtils.TEST_QUERY_CONTEXT);
- for (int i = 19; i >= 8; i--) {
- assertTrue(dataSet.hasNext());
- assertEquals(i + "\t8", dataSet.next().toString());
- }
- assertTrue(dataSet.hasNext());
- assertEquals("7\t7", dataSet.next().toString());
- assertTrue(dataSet.hasNext());
- assertEquals("6\t6", dataSet.next().toString());
- assertTrue(dataSet.hasNext());
- assertEquals("5\t1", dataSet.next().toString());
- }
-
- @Test
- public void groupByWithCross() throws Exception {
- QueryPlan queryPlan =
- (QueryPlan)
- processor.parseSQLToPhysicalPlan(
- "select last_value(s0) from root.vehicle.* where s2 > 1 group by ([0,20), 1ms) fill (int32[Previous]) order by time desc");
- QueryDataSet dataSet =
- queryExecutor.processQuery(queryPlan, EnvironmentUtils.TEST_QUERY_CONTEXT);
- for (int i = 19; i >= 8; i--) {
- assertTrue(dataSet.hasNext());
- assertEquals(i + "\t7", dataSet.next().toString());
- }
- assertTrue(dataSet.hasNext());
- assertEquals("7\t7", dataSet.next().toString());
- assertTrue(dataSet.hasNext());
- assertEquals("6\t6", dataSet.next().toString());
- for (int i = 5; i >= 0; i--) {
- assertTrue(dataSet.hasNext());
- assertEquals(i + "\tnull", dataSet.next().toString());
- }
- }
+ // @Test
+ // public void groupByWithAndFilterFillTest() throws Exception {
+ // QueryPlan queryPlan =
+ // (QueryPlan)
+ // processor.parseSQLToPhysicalPlan(
+ // "select last_value(s0) from root.vehicle.* where s1 > 1 or s0 > 1 group by
+ // ([0,20), 1ms) fill (int32[Previous]) order by time desc");
+ // QueryDataSet dataSet =
+ // queryExecutor.processQuery(queryPlan, EnvironmentUtils.TEST_QUERY_CONTEXT);
+ // for (int i = 19; i >= 8; i--) {
+ // assertTrue(dataSet.hasNext());
+ // assertEquals(i + "\t8", dataSet.next().toString());
+ // }
+ // assertTrue(dataSet.hasNext());
+ // assertEquals("7\t7", dataSet.next().toString());
+ // assertTrue(dataSet.hasNext());
+ // assertEquals("6\t6", dataSet.next().toString());
+ // for (int i = 5; i >= 0; i--) {
+ // assertTrue(dataSet.hasNext());
+ // assertEquals(i + "\tnull", dataSet.next().toString());
+ // }
+ // }
+ //
+ // @Test
+ // public void groupByWithFirstNullTest() throws Exception {
+ // QueryPlan queryPlan =
+ // (QueryPlan)
+ // processor.parseSQLToPhysicalPlan(
+ // "select last_value(s0) from root.vehicle.* where s1 > 1 or s0 > 1 group by
+ // ([5,20), 1ms) fill (int32[Previous]) order by time desc");
+ // QueryDataSet dataSet =
+ // queryExecutor.processQuery(queryPlan, EnvironmentUtils.TEST_QUERY_CONTEXT);
+ // for (int i = 19; i >= 8; i--) {
+ // assertTrue(dataSet.hasNext());
+ // assertEquals(i + "\t8", dataSet.next().toString());
+ // }
+ // assertTrue(dataSet.hasNext());
+ // assertEquals("7\t7", dataSet.next().toString());
+ // assertTrue(dataSet.hasNext());
+ // assertEquals("6\t6", dataSet.next().toString());
+ // assertTrue(dataSet.hasNext());
+ // assertEquals("5\t1", dataSet.next().toString());
+ // }
+ //
+ // @Test
+ // public void groupByWithCross() throws Exception {
+ // QueryPlan queryPlan =
+ // (QueryPlan)
+ // processor.parseSQLToPhysicalPlan(
+ // "select last_value(s0) from root.vehicle.* where s2 > 1 group by ([0,20), 1ms)
+ // fill (int32[Previous]) order by time desc");
+ // QueryDataSet dataSet =
+ // queryExecutor.processQuery(queryPlan, EnvironmentUtils.TEST_QUERY_CONTEXT);
+ // for (int i = 19; i >= 8; i--) {
+ // assertTrue(dataSet.hasNext());
+ // assertEquals(i + "\t7", dataSet.next().toString());
+ // }
+ // assertTrue(dataSet.hasNext());
+ // assertEquals("7\t7", dataSet.next().toString());
+ // assertTrue(dataSet.hasNext());
+ // assertEquals("6\t6", dataSet.next().toString());
+ // for (int i = 5; i >= 0; i--) {
+ // assertTrue(dataSet.hasNext());
+ // assertEquals(i + "\tnull", dataSet.next().toString());
+ // }
+ // }
}
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/RowRecord.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/RowRecord.java
index df0c051..748e8ab 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/RowRecord.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/RowRecord.java
@@ -25,7 +25,7 @@ import java.util.List;
public class RowRecord {
- private final long timestamp;
+ private long timestamp;
private final List<Field> fields;
/** if any column is null, this field should be set to true; otherwise false */
private boolean hasNullField = false;
@@ -79,6 +79,10 @@ public class RowRecord {
return sb.toString();
}
+ public void setTimestamp(long timestamp) {
+ this.timestamp = timestamp;
+ }
+
public long getTimestamp() {
return timestamp;
}