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 59eb9bbb0a9 Fix explicit time query process in TreeModel 59eb9bbb0a9 is described below commit 59eb9bbb0a937f9315bd78bd3e0ccd81d67da7e7 Author: Weihao Li <60659567+wei-hao...@users.noreply.github.com> AuthorDate: Mon Jul 14 17:02:43 2025 +0800 Fix explicit time query process in TreeModel --- .../aggregation/maxby/IoTDBMaxByAlignedSeriesIT.java | 20 ++++++++++++++++++++ .../iotdb/db/it/aggregation/maxby/IoTDBMaxByIT.java | 16 ++++++++++++++++ .../execution/operator/process/ProjectOperator.java | 3 ++- .../plan/planner/OperatorTreeGenerator.java | 6 +++++- .../dag/input/QueryDataSetInputLayer.java | 3 +++ 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/aggregation/maxby/IoTDBMaxByAlignedSeriesIT.java b/integration-test/src/test/java/org/apache/iotdb/db/it/aggregation/maxby/IoTDBMaxByAlignedSeriesIT.java index bdcce214db8..cf3a5d6cea8 100644 --- a/integration-test/src/test/java/org/apache/iotdb/db/it/aggregation/maxby/IoTDBMaxByAlignedSeriesIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/db/it/aggregation/maxby/IoTDBMaxByAlignedSeriesIT.java @@ -22,8 +22,10 @@ package org.apache.iotdb.db.it.aggregation.maxby; import org.apache.iotdb.it.env.EnvFactory; import org.junit.BeforeClass; +import org.junit.Test; import static org.apache.iotdb.db.it.utils.TestUtils.prepareData; +import static org.apache.iotdb.db.it.utils.TestUtils.resultSetEqualTest; public class IoTDBMaxByAlignedSeriesIT extends IoTDBMaxByIT { protected static final String[] ALIGNED_DATASET = @@ -60,6 +62,7 @@ public class IoTDBMaxByAlignedSeriesIT extends IoTDBMaxByIT { "INSERT INTO root.db.d2(timestamp,y1,y2,y3,y4,y5,y6) values(12, 8, 8, 8, 8, false, \"4\")", "INSERT INTO root.db.d2(timestamp,x1,x2,x3,x4,x5,x6) values(13, 4, 4, 4, 4, false, \"4\")", "INSERT INTO root.db.d2(timestamp,y1,y2,y3,y4,y5,y6) values(13, 8, 8, 8, 8, false, \"4\")", + "insert into root.sg.d1(time,s1,s2) values(1,1,1);", }; @BeforeClass @@ -68,4 +71,21 @@ public class IoTDBMaxByAlignedSeriesIT extends IoTDBMaxByIT { EnvFactory.getEnv().initClusterEnvironment(); prepareData(ALIGNED_DATASET); } + + @Test + public void maxMinByTimeTest() { + String[] expectedHeader = + new String[] {"Device", "max_by(Time, s1 + 1)", "min_by(Time, s1 + 1)"}; + String[] retArray = new String[] {"root.sg.d1,1,1,"}; + resultSetEqualTest( + "select max_by(time, s1+1), min_by(time, s1+1) from root.sg.* align by device", + expectedHeader, + retArray); + + expectedHeader = new String[] {"Device", "max_by(Time, s1)", "min_by(Time, s1)"}; + resultSetEqualTest( + "select max_by(time, s1), min_by(time, s1) from root.sg.* where s1>0 align by device", + expectedHeader, + retArray); + } } diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/aggregation/maxby/IoTDBMaxByIT.java b/integration-test/src/test/java/org/apache/iotdb/db/it/aggregation/maxby/IoTDBMaxByIT.java index 558cbe36d24..540c8bc6671 100644 --- a/integration-test/src/test/java/org/apache/iotdb/db/it/aggregation/maxby/IoTDBMaxByIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/db/it/aggregation/maxby/IoTDBMaxByIT.java @@ -111,6 +111,7 @@ public class IoTDBMaxByIT { "INSERT INTO root.db.d2(timestamp,y1,y2,y3,y4,y5,y6) values(12, 9, 9, 9, 9, false, \"1\")", "INSERT INTO root.db.d2(timestamp,x1,x2,x3,x4,x5,x6) values(13, 4, 4, 4, 4, false, \"4\")", "INSERT INTO root.db.d2(timestamp,y1,y2,y3,y4,y5,y6) values(13, 9, 9, 9, 9, false, \"1\")", + "insert into root.sg.d1(time,s1,s2) values(1,1,1);", "flush" }; @@ -487,6 +488,21 @@ public class IoTDBMaxByIT { } } + @Test + public void maxMinByTimeTest() { + String[] expectedHeader = + new String[] {"max_by(Time, root.sg.d1.s1 + 1)", "min_by(Time, root.sg.d1.s1 + 1)"}; + String[] retArray = new String[] {"1,1,"}; + resultSetEqualTest( + "select max_by(time, s1+1), min_by(time, s1+1) from root.sg.*", expectedHeader, retArray); + + expectedHeader = new String[] {"max_by(Time, root.sg.d1.s1)", "min_by(Time, root.sg.d1.s1)"}; + resultSetEqualTest( + "select max_by(time, s1), min_by(time, s1) from root.sg.* where s1>0", + expectedHeader, + retArray); + } + /** * @return yInput -> expectedHeader */ diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/ProjectOperator.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/ProjectOperator.java index bb4ffc7b74e..9c4cd266143 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/ProjectOperator.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/ProjectOperator.java @@ -68,7 +68,8 @@ public class ProjectOperator implements ProcessOperator { } Column[] valueColumns = new Column[remainingColumnIndexList.size()]; for (int i = 0; i < remainingColumnIndexList.size(); i++) { - valueColumns[i] = input.getColumn(remainingColumnIndexList.get(i)); + int index = remainingColumnIndexList.get(i); + valueColumns[i] = index == -1 ? input.getTimeColumn() : input.getColumn(index); } return new TsBlock(input.getPositionCount(), input.getTimeColumn(), valueColumns); } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java index a6a79247b0a..505af22ffc7 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java @@ -606,7 +606,7 @@ public class OperatorTreeGenerator extends PlanVisitor<Operator, LocalExecutionP List<Integer> remainingColumnIndexList = new ArrayList<>(); for (String outputColumnName : outputColumnNames) { int index = inputColumnNames.indexOf(outputColumnName); - if (index < 0) { + if (index < 0 && !outputColumnName.equals(TIMESTAMP_EXPRESSION_STRING)) { throw new IllegalStateException( String.format("Cannot find column [%s] in child's output", outputColumnName)); } @@ -3219,6 +3219,10 @@ public class OperatorTreeGenerator extends PlanVisitor<Operator, LocalExecutionP .add(new InputLocation(tsBlockIndex, -1)); int valueColumnIndex = 0; for (String columnName : childNode.getOutputColumnNames()) { + if (columnName.equals(TIMESTAMP_EXPRESSION_STRING)) { + valueColumnIndex++; + continue; + } outputMappings .computeIfAbsent(columnName, key -> new ArrayList<>()) .add(new InputLocation(tsBlockIndex, valueColumnIndex)); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/input/QueryDataSetInputLayer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/input/QueryDataSetInputLayer.java index d0db0f2b58c..d13dfb3ced4 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/input/QueryDataSetInputLayer.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/input/QueryDataSetInputLayer.java @@ -129,6 +129,9 @@ public class QueryDataSetInputLayer { @Override public TSDataType[] getDataTypes() { + if (columnIndex == dataTypes.length) { + return new TSDataType[] {TSDataType.INT64}; + } return new TSDataType[] {dataTypes[columnIndex]}; }