From 6f2bbffe8a5ff2b18815ee2d361f3144564449da Mon Sep 17 00:00:00 2001 From: shuwenwei Date: Wed, 3 Dec 2025 16:58:06 +0800 Subject: [PATCH 1/2] fix showQueries --- .../queryengine/plan/parser/ASTVisitor.java | 22 ++++++++++--- .../distribution/ExchangeNodeAdder.java | 6 ++-- .../plan/node/source/ShowQueriesNode.java | 2 +- .../statement/component/OrderByComponent.java | 6 ++++ .../FragmentInstanceStatisticsDrawer.java | 2 +- .../plan/parser/StatementGeneratorTest.java | 33 +++++++++++++++++++ 6 files changed, 62 insertions(+), 9 deletions(-) diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java index 7f3936af51150..fafa0995db170 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java @@ -1634,7 +1634,8 @@ public Statement visitSelectStatement(IoTDBSqlParser.SelectStatementContext ctx) queryStatement.setOrderByComponent( parseOrderByClause( ctx.orderByClause(), - ImmutableSet.of(OrderByKey.TIME, OrderByKey.DEVICE, OrderByKey.TIMESERIES))); + ImmutableSet.of(OrderByKey.TIME, OrderByKey.DEVICE, OrderByKey.TIMESERIES), + true)); } // parse FILL @@ -1937,7 +1938,9 @@ private HavingCondition parseHavingClause(IoTDBSqlParser.HavingClauseContext ctx // ---- Order By Clause // all SortKeys should be contained by limitSet private OrderByComponent parseOrderByClause( - IoTDBSqlParser.OrderByClauseContext ctx, ImmutableSet limitSet) { + IoTDBSqlParser.OrderByClauseContext ctx, + ImmutableSet limitSet, + boolean allowExpression) { OrderByComponent orderByComponent = new OrderByComponent(); Set sortKeySet = new HashSet<>(); for (IoTDBSqlParser.OrderByAttributeClauseContext orderByAttributeClauseContext : @@ -1946,7 +1949,8 @@ private OrderByComponent parseOrderByClause( if (orderByComponent.isUnique()) { break; } - SortItem sortItem = parseOrderByAttributeClause(orderByAttributeClauseContext, limitSet); + SortItem sortItem = + parseOrderByAttributeClause(orderByAttributeClauseContext, limitSet, allowExpression); String sortKey = sortItem.getSortKey(); if (sortKeySet.contains(sortKey)) { @@ -1965,7 +1969,9 @@ private OrderByComponent parseOrderByClause( } private SortItem parseOrderByAttributeClause( - IoTDBSqlParser.OrderByAttributeClauseContext ctx, ImmutableSet limitSet) { + IoTDBSqlParser.OrderByAttributeClauseContext ctx, + ImmutableSet limitSet, + boolean allowExpression) { if (ctx.sortKey() != null) { String sortKey = ctx.sortKey().getText().toUpperCase(); if (!limitSet.contains(sortKey)) { @@ -1974,6 +1980,11 @@ private SortItem parseOrderByAttributeClause( } return new SortItem(sortKey, ctx.DESC() != null ? Ordering.DESC : Ordering.ASC); } else { + if (!allowExpression) { + throw new SemanticException( + "ORDER BY expression is not supported for current statement, supported sort key: " + + limitSet.toString()); + } Expression sortExpression = parseExpression(ctx.expression(), true); return new SortItem( sortExpression, @@ -3719,7 +3730,8 @@ public Statement visitShowQueries(IoTDBSqlParser.ShowQueriesContext ctx) { OrderByKey.QUERYID, OrderByKey.DATANODEID, OrderByKey.ELAPSEDTIME, - OrderByKey.STATEMENT))); + OrderByKey.STATEMENT), + false)); } // parse LIMIT & OFFSET diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/ExchangeNodeAdder.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/ExchangeNodeAdder.java index 8f36e44361a3d..69105a094d151 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/ExchangeNodeAdder.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/ExchangeNodeAdder.java @@ -567,10 +567,12 @@ private PlanNode processOneChildNode(PlanNode node, NodeGroupContext context) { PlanNode newNode = node.clone(); PlanNode child = visit(node.getChildren().get(0), context); newNode.addChild(child); - TRegionReplicaSet dataRegion = context.getNodeDistribution(child.getPlanNodeId()).getRegion(); + NodeDistribution nodeDistribution = context.getNodeDistribution(child.getPlanNodeId()); context.putNodeDistribution( newNode.getPlanNodeId(), - new NodeDistribution(NodeDistributionType.SAME_WITH_ALL_CHILDREN, dataRegion)); + new NodeDistribution( + NodeDistributionType.SAME_WITH_ALL_CHILDREN, + nodeDistribution == null ? null : nodeDistribution.getRegion())); return newNode; } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/source/ShowQueriesNode.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/source/ShowQueriesNode.java index c5925f93480e9..25e94c0da5cb9 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/source/ShowQueriesNode.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/source/ShowQueriesNode.java @@ -105,8 +105,8 @@ protected void serializeAttributes(DataOutputStream stream) throws IOException { } public static ShowQueriesNode deserialize(ByteBuffer byteBuffer) { - PlanNodeId planNodeId = PlanNodeId.deserialize(byteBuffer); String allowedUsername = ReadWriteIOUtils.readString(byteBuffer); + PlanNodeId planNodeId = PlanNodeId.deserialize(byteBuffer); return new ShowQueriesNode(planNodeId, null, allowedUsername); } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/component/OrderByComponent.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/component/OrderByComponent.java index 8774db378f55b..b6aa8c67c0a9d 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/component/OrderByComponent.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/component/OrderByComponent.java @@ -63,6 +63,12 @@ public void addSortItem(SortItem sortItem) { orderByDevice = true; deviceOrderPriority = sortItemList.size() - 1; break; + case OrderByKey.QUERYID: + case OrderByKey.DATANODEID: + case OrderByKey.ELAPSEDTIME: + case OrderByKey.STATEMENT: + // show queries statement + break; default: throw new IllegalArgumentException( String.format("Unknown sort key %s", sortItem.getSortKey())); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/statistics/FragmentInstanceStatisticsDrawer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/statistics/FragmentInstanceStatisticsDrawer.java index b9f1a55b5bdf2..7a8b7097eb9bd 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/statistics/FragmentInstanceStatisticsDrawer.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/statistics/FragmentInstanceStatisticsDrawer.java @@ -484,7 +484,7 @@ private void renderOperator( addLineWithValueCheck( singleFragmentInstanceArea, indentNum + 2, - "Estimated Memory Size: ", + "Estimated Memory Size", operatorStatistic.getMemoryUsage()); if (operatorStatistic.getSpecifiedInfoSize() != 0) { diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/parser/StatementGeneratorTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/parser/StatementGeneratorTest.java index 9da2cdcf8a49a..4d27792e5328b 100644 --- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/parser/StatementGeneratorTest.java +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/parser/StatementGeneratorTest.java @@ -39,7 +39,10 @@ import org.apache.iotdb.db.queryengine.plan.statement.Statement; import org.apache.iotdb.db.queryengine.plan.statement.StatementTestUtils; import org.apache.iotdb.db.queryengine.plan.statement.StatementType; +import org.apache.iotdb.db.queryengine.plan.statement.component.OrderByKey; +import org.apache.iotdb.db.queryengine.plan.statement.component.Ordering; import org.apache.iotdb.db.queryengine.plan.statement.component.ResultColumn; +import org.apache.iotdb.db.queryengine.plan.statement.component.SortItem; import org.apache.iotdb.db.queryengine.plan.statement.crud.DeleteDataStatement; import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertMultiTabletsStatement; import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowStatement; @@ -60,6 +63,7 @@ import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.UnsetSchemaTemplateStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.view.CreateLogicalViewStatement; import org.apache.iotdb.db.queryengine.plan.statement.sys.AuthorStatement; +import org.apache.iotdb.db.queryengine.plan.statement.sys.ShowQueriesStatement; import org.apache.iotdb.isession.template.TemplateNode; import org.apache.iotdb.rpc.StatementExecutionException; import org.apache.iotdb.service.rpc.thrift.TSAggregationQueryReq; @@ -116,6 +120,35 @@ public class StatementGeneratorTest { + @Test + public void testShowQueries() { + Statement showQueries = + StatementGenerator.createStatement( + "show queries order by time, queryid, datanodeid, elapsedtime, statement", + ZonedDateTime.now().getOffset()); + Assert.assertTrue(showQueries instanceof ShowQueriesStatement); + Assert.assertEquals( + ((ShowQueriesStatement) showQueries).getSortItemList().get(0), + new SortItem(OrderByKey.TIME, Ordering.ASC)); + Assert.assertEquals( + ((ShowQueriesStatement) showQueries).getSortItemList().get(1), + new SortItem(OrderByKey.QUERYID, Ordering.ASC)); + Assert.assertEquals( + ((ShowQueriesStatement) showQueries).getSortItemList().get(2), + new SortItem(OrderByKey.DATANODEID, Ordering.ASC)); + Assert.assertEquals( + ((ShowQueriesStatement) showQueries).getSortItemList().get(3), + new SortItem(OrderByKey.ELAPSEDTIME, Ordering.ASC)); + Assert.assertEquals( + ((ShowQueriesStatement) showQueries).getSortItemList().get(4), + new SortItem(OrderByKey.STATEMENT, Ordering.ASC)); + Assert.assertThrows( + SemanticException.class, + () -> + StatementGenerator.createStatement( + "show queries order by a", ZonedDateTime.now().getOffset())); + } + @Test public void testRawDataQuery() throws IllegalPathException { TSRawDataQueryReq req = From b0a6e003561525d67e6ee89af347e8299cb4bb2a Mon Sep 17 00:00:00 2001 From: shuwenwei Date: Wed, 3 Dec 2025 18:38:27 +0800 Subject: [PATCH 2/2] fix codecov --- ...erdeTest.java => SourceNodeSerdeTest.java} | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) rename iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/node/source/{LastQueryScanNodeSerdeTest.java => SourceNodeSerdeTest.java} (76%) diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/node/source/LastQueryScanNodeSerdeTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/node/source/SourceNodeSerdeTest.java similarity index 76% rename from iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/node/source/LastQueryScanNodeSerdeTest.java rename to iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/node/source/SourceNodeSerdeTest.java index 68a7fa0df0d36..068b2bbc4b6f7 100644 --- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/node/source/LastQueryScanNodeSerdeTest.java +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/node/source/SourceNodeSerdeTest.java @@ -24,6 +24,7 @@ import org.apache.iotdb.db.queryengine.plan.planner.node.PlanNodeDeserializeHelper; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNodeId; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.source.LastQueryScanNode; +import org.apache.iotdb.db.queryengine.plan.planner.plan.node.source.ShowQueriesNode; import org.apache.tsfile.enums.TSDataType; import org.apache.tsfile.write.schema.MeasurementSchema; @@ -34,9 +35,9 @@ import static org.junit.Assert.assertEquals; -public class LastQueryScanNodeSerdeTest { +public class SourceNodeSerdeTest { @Test - public void test() throws IllegalPathException { + public void testLastQueryScanNode() throws IllegalPathException { LastQueryScanNode node = new LastQueryScanNode( new PlanNodeId("test"), @@ -69,4 +70,19 @@ public void test() throws IllegalPathException { byteBuffer.flip(); assertEquals(PlanNodeDeserializeHelper.deserialize(byteBuffer), node); } + + @Test + public void testShowQueriesNode() throws IllegalPathException { + ShowQueriesNode node = new ShowQueriesNode(new PlanNodeId("test"), null, "root"); + + ByteBuffer byteBuffer = ByteBuffer.allocate(2048); + node.serialize(byteBuffer); + byteBuffer.flip(); + assertEquals(PlanNodeDeserializeHelper.deserialize(byteBuffer), node); + node = new ShowQueriesNode(new PlanNodeId("test"), null, "root"); + byteBuffer = ByteBuffer.allocate(2048); + node.serialize(byteBuffer); + byteBuffer.flip(); + assertEquals(PlanNodeDeserializeHelper.deserialize(byteBuffer), node); + } }