You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ca...@apache.org on 2024/09/13 02:09:28 UTC
(iotdb) 01/01: Fix error in last query with sort + limit
This is an automated email from the ASF dual-hosted git repository.
caogaofei pushed a commit to branch beyyes/cp_133
in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 92ef1bad842a0ee9702e421732bdbc2ee7fe2072
Author: Beyyes <cg...@foxmail.com>
AuthorDate: Fri Sep 13 10:02:05 2024 +0800
Fix error in last query with sort + limit
---
.../db/it/last/IoTDBLastQueryLastCacheIT.java | 14 +++++++++
.../it/last/IoTDBLastQueryWithLimitOffsetIT.java | 34 ++++++++++++++++++++++
.../plan/planner/LogicalPlanVisitor.java | 11 +++----
.../plan/node/process/last/LastQueryNode.java | 3 ++
.../logical/DataQueryLogicalPlannerTest.java | 33 +++++++++++++++++++++
5 files changed, 90 insertions(+), 5 deletions(-)
diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/last/IoTDBLastQueryLastCacheIT.java b/integration-test/src/test/java/org/apache/iotdb/db/it/last/IoTDBLastQueryLastCacheIT.java
index 6d30db00085..feb710be4fa 100644
--- a/integration-test/src/test/java/org/apache/iotdb/db/it/last/IoTDBLastQueryLastCacheIT.java
+++ b/integration-test/src/test/java/org/apache/iotdb/db/it/last/IoTDBLastQueryLastCacheIT.java
@@ -165,4 +165,18 @@ public class IoTDBLastQueryLastCacheIT {
testLastQueryOrderByTimeDesc();
testLastQuery1();
}
+
+ @Test
+ public void testLastQuerySortWithLimit() {
+ String[] expectedHeader =
+ new String[] {TIMESTAMP_STR, TIMESEIRES_STR, VALUE_STR, DATA_TYPE_STR};
+ String[] retArray =
+ new String[] {
+ "1679477545000,root.ln_1.tb_6141.code_DOUBLE,2.0,DOUBLE,",
+ };
+ resultSetEqualTest(
+ "select last * from root.ln_1.tb_6141 order by time desc, timeseries desc limit 1;",
+ expectedHeader,
+ retArray);
+ }
}
diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/last/IoTDBLastQueryWithLimitOffsetIT.java b/integration-test/src/test/java/org/apache/iotdb/db/it/last/IoTDBLastQueryWithLimitOffsetIT.java
index 062d5a345c3..0de811ff271 100644
--- a/integration-test/src/test/java/org/apache/iotdb/db/it/last/IoTDBLastQueryWithLimitOffsetIT.java
+++ b/integration-test/src/test/java/org/apache/iotdb/db/it/last/IoTDBLastQueryWithLimitOffsetIT.java
@@ -190,4 +190,38 @@ public class IoTDBLastQueryWithLimitOffsetIT {
fail(e.getMessage());
}
}
+
+ @Test
+ public void testWithSortLimit() {
+ String[] retArray =
+ new String[] {
+ "2,root.sg.d2.s2,1.0,DOUBLE",
+ };
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+
+ try (ResultSet resultSet =
+ statement.executeQuery(
+ "select last * from root.sg.** order by time desc, timeseries desc limit 1")) {
+ int cnt = 0;
+ while (resultSet.next()) {
+ String ans =
+ resultSet.getString(ColumnHeaderConstant.TIME)
+ + ","
+ + resultSet.getString(ColumnHeaderConstant.TIMESERIES)
+ + ","
+ + resultSet.getString(ColumnHeaderConstant.VALUE)
+ + ","
+ + resultSet.getString(ColumnHeaderConstant.DATATYPE);
+ assertEquals(retArray[cnt++], ans);
+ }
+ assertEquals(retArray.length, cnt);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanVisitor.java
index 5913bc9f665..86bc69f27e3 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanVisitor.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanVisitor.java
@@ -142,15 +142,16 @@ public class LogicalPlanVisitor extends StatementVisitor<PlanNode, MPPQueryConte
LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(analysis, context);
if (queryStatement.isLastQuery()) {
- planBuilder =
- planBuilder
- .planLast(analysis, analysis.getTimeseriesOrderingForLastQuery())
- .planOffset(queryStatement.getRowOffset())
- .planLimit(queryStatement.getRowLimit());
+ planBuilder = planBuilder.planLast(analysis, analysis.getTimeseriesOrderingForLastQuery());
if (queryStatement.hasOrderBy() && !queryStatement.onlyOrderByTimeseries()) {
planBuilder = planBuilder.planOrderBy(queryStatement.getSortItemList());
}
+
+ planBuilder =
+ planBuilder
+ .planOffset(queryStatement.getRowOffset())
+ .planLimit(queryStatement.getRowLimit());
return planBuilder.getRoot();
}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/process/last/LastQueryNode.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/process/last/LastQueryNode.java
index 2fb059f8b2e..5d0589e40d4 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/process/last/LastQueryNode.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/process/last/LastQueryNode.java
@@ -110,6 +110,9 @@ public class LastQueryNode extends MultiChildProcessNode {
return false;
}
LastQueryNode that = (LastQueryNode) o;
+ if (timeseriesOrdering == null) {
+ return that.timeseriesOrdering == null;
+ }
return timeseriesOrdering.equals(that.timeseriesOrdering);
}
diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/logical/DataQueryLogicalPlannerTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/logical/DataQueryLogicalPlannerTest.java
index 2a14c0cf3b2..993b15562ea 100644
--- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/logical/DataQueryLogicalPlannerTest.java
+++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/logical/DataQueryLogicalPlannerTest.java
@@ -36,6 +36,7 @@ import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.GroupByLev
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.LimitNode;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.OffsetNode;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.RawDataAggregationNode;
+import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.SortNode;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.join.FullOuterTimeJoinNode;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.last.LastQueryNode;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.source.AlignedLastQueryScanNode;
@@ -105,6 +106,38 @@ public class DataQueryLogicalPlannerTest {
Assert.assertEquals(actualPlan, lastQueryNode);
}
+ @Test
+ public void testLastQuerySortWithLimit() {
+ String sql = "SELECT last * FROM root.sg.d1 ORDER BY time DESC LIMIT 1";
+
+ QueryId queryId = new QueryId("test");
+ // fake initResultNodeContext()
+ queryId.genPlanNodeId();
+
+ LastQueryScanNode d1s3 =
+ new LastQueryScanNode(
+ queryId.genPlanNodeId(), (MeasurementPath) schemaMap.get("root.sg.d1.s3"), null);
+ LastQueryScanNode d1s1 =
+ new LastQueryScanNode(
+ queryId.genPlanNodeId(), (MeasurementPath) schemaMap.get("root.sg.d1.s1"), null);
+ LastQueryScanNode d1s2 =
+ new LastQueryScanNode(
+ queryId.genPlanNodeId(), (MeasurementPath) schemaMap.get("root.sg.d1.s2"), null);
+
+ List<PlanNode> sourceNodeList = Arrays.asList(d1s3, d1s1, d1s2);
+ LastQueryNode lastQueryNode =
+ new LastQueryNode(queryId.genPlanNodeId(), sourceNodeList, null, false);
+ SortNode sortNode =
+ new SortNode(
+ queryId.genPlanNodeId(),
+ lastQueryNode,
+ new OrderByParameter(Collections.singletonList(new SortItem("TIME", Ordering.DESC))));
+ LimitNode limitNode = new LimitNode(queryId.genPlanNodeId(), sortNode, 1);
+
+ PlanNode actualPlan = parseSQLToPlanNode(sql);
+ Assert.assertEquals(actualPlan, limitNode);
+ }
+
@Test
public void testSimpleRawDataQuery() {
String sql = "SELECT ** FROM root.sg.d2 WHERE time > 100 LIMIT 10 OFFSET 10";