This is an automated email from the ASF dual-hosted git repository. weihao pushed a commit to branch descQ in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 232f7f4a033c6ca098f447f377dc6403005ea9ea Author: Weihao Li <[email protected]> AuthorDate: Wed Apr 1 09:48:50 2026 +0800 implement Signed-off-by: Weihao Li <[email protected]> --- .../iotdb/relational/it/schema/IoTDBTableIT.java | 91 ++++++++++++++++++++++ .../common/header/DatasetHeaderFactory.java | 4 + .../TableModelStatementMemorySourceVisitor.java | 42 ++++++++++ .../relational/analyzer/StatementAnalyzer.java | 7 ++ .../relational/planner/TableLogicalPlanner.java | 8 +- .../plan/relational/planner/node/OutputNode.java | 9 +++ .../plan/relational/sql/ast/AstVisitor.java | 4 + .../sql/ast/DefaultTraversalVisitor.java | 6 ++ .../plan/relational/sql/ast/DescribeQuery.java | 86 ++++++++++++++++++++ .../plan/relational/sql/parser/AstBuilder.java | 6 ++ .../schema/column/ColumnHeaderConstant.java | 5 ++ .../db/relational/grammar/sql/RelationalSql.g4 | 5 ++ 12 files changed, 267 insertions(+), 6 deletions(-) diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBTableIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBTableIT.java index b335278321c..d81cceab58a 100644 --- a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBTableIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBTableIT.java @@ -53,6 +53,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import static org.apache.iotdb.commons.schema.column.ColumnHeaderConstant.describeQueryColumnHeaders; import static org.apache.iotdb.commons.schema.column.ColumnHeaderConstant.describeTableColumnHeaders; import static org.apache.iotdb.commons.schema.column.ColumnHeaderConstant.describeTableDetailsColumnHeaders; import static org.apache.iotdb.commons.schema.column.ColumnHeaderConstant.showDBColumnHeaders; @@ -435,6 +436,96 @@ public class IoTDBTableIT { assertEquals(columnNames.length, cnt); } + columnNames = new String[] {"region_id", "_col1"}; + dataTypes = new String[] {"STRING", "FLOAT"}; + try (final ResultSet resultSet = + statement.executeQuery( + "describe select region_id, max(temperature) from test1.table1 group by region_id")) { + int cnt = 0; + ResultSetMetaData metaData = resultSet.getMetaData(); + assertEquals(describeQueryColumnHeaders.size(), metaData.getColumnCount()); + for (int i = 0; i < describeQueryColumnHeaders.size(); i++) { + assertEquals( + describeQueryColumnHeaders.get(i).getColumnName(), metaData.getColumnName(i + 1)); + } + while (resultSet.next()) { + assertEquals(columnNames[cnt], resultSet.getString(1)); + assertEquals(dataTypes[cnt], resultSet.getString(2)); + cnt++; + } + assertEquals(columnNames.length, cnt); + } + + // describe query: last + group by + columnNames = new String[] {"last_time", "last_temp"}; + dataTypes = new String[] {"TIMESTAMP", "FLOAT"}; + try (final ResultSet resultSet = + statement.executeQuery( + "describe select last(time) as last_time, last(temperature) as last_temp " + + "from test1.table1")) { + int cnt = 0; + ResultSetMetaData metaData = resultSet.getMetaData(); + assertEquals(describeQueryColumnHeaders.size(), metaData.getColumnCount()); + for (int i = 0; i < describeQueryColumnHeaders.size(); i++) { + assertEquals( + describeQueryColumnHeaders.get(i).getColumnName(), metaData.getColumnName(i + 1)); + } + while (resultSet.next()) { + assertEquals(columnNames[cnt], resultSet.getString(1)); + assertEquals(dataTypes[cnt], resultSet.getString(2)); + cnt++; + } + assertEquals(columnNames.length, cnt); + } + + // describe query: date_bin + group by + aggregate + columnNames = new String[] {"bucket", "region_id", "max_t"}; + dataTypes = new String[] {"TIMESTAMP", "STRING", "FLOAT"}; + try (final ResultSet resultSet = + statement.executeQuery( + "describe select date_bin(5s, time) as bucket, region_id, max(temperature) as max_t " + + "from test1.table1 group by 1, 2")) { + int cnt = 0; + ResultSetMetaData metaData = resultSet.getMetaData(); + assertEquals(describeQueryColumnHeaders.size(), metaData.getColumnCount()); + for (int i = 0; i < describeQueryColumnHeaders.size(); i++) { + assertEquals( + describeQueryColumnHeaders.get(i).getColumnName(), metaData.getColumnName(i + 1)); + } + while (resultSet.next()) { + assertEquals(columnNames[cnt], resultSet.getString(1)); + assertEquals(dataTypes[cnt], resultSet.getString(2)); + cnt++; + } + assertEquals(columnNames.length, cnt); + } + + // describe query: raw row scan (no aggregation) + columnNames = + new String[] { + "time", "region_id", "plant_id", "device_id", "model", "temperature", "humidity" + }; + dataTypes = + new String[] {"TIMESTAMP", "STRING", "STRING", "STRING", "STRING", "FLOAT", "DOUBLE"}; + try (final ResultSet resultSet = + statement.executeQuery( + "describe select time, region_id, plant_id, device_id, model, temperature, humidity " + + "from test1.table1 where region_id = 'r1'")) { + int cnt = 0; + ResultSetMetaData metaData = resultSet.getMetaData(); + assertEquals(describeQueryColumnHeaders.size(), metaData.getColumnCount()); + for (int i = 0; i < describeQueryColumnHeaders.size(); i++) { + assertEquals( + describeQueryColumnHeaders.get(i).getColumnName(), metaData.getColumnName(i + 1)); + } + while (resultSet.next()) { + assertEquals(columnNames[cnt], resultSet.getString(1)); + assertEquals(dataTypes[cnt], resultSet.getString(2)); + cnt++; + } + assertEquals(columnNames.length, cnt); + } + statement.execute( "insert into table2(region_id, plant_id, color, temperature, speed) values(1, 1, 1, 1, 1)"); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/header/DatasetHeaderFactory.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/header/DatasetHeaderFactory.java index 18f15eea8f3..c28c57b3607 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/header/DatasetHeaderFactory.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/header/DatasetHeaderFactory.java @@ -251,6 +251,10 @@ public class DatasetHeaderFactory { return new DatasetHeader(ColumnHeaderConstant.describeTableColumnHeaders, true); } + public static DatasetHeader getDescribeQueryHeader() { + return new DatasetHeader(ColumnHeaderConstant.describeQueryColumnHeaders, true); + } + public static DatasetHeader getDescribeTableDetailsHeader() { return new DatasetHeader(ColumnHeaderConstant.describeTableDetailsColumnHeaders, true); } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceVisitor.java index 932d9419792..3d39758a83b 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceVisitor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceVisitor.java @@ -21,26 +21,35 @@ package org.apache.iotdb.db.queryengine.plan.execution.memory; import org.apache.iotdb.commons.conf.IoTDBConstant; import org.apache.iotdb.commons.schema.column.ColumnHeader; +import org.apache.iotdb.commons.schema.column.ColumnHeaderConstant; import org.apache.iotdb.db.queryengine.common.header.DatasetHeader; +import org.apache.iotdb.db.queryengine.common.header.DatasetHeaderFactory; import org.apache.iotdb.db.queryengine.plan.Coordinator; import org.apache.iotdb.db.queryengine.plan.planner.LocalExecutionPlanner; import org.apache.iotdb.db.queryengine.plan.planner.plan.LogicalQueryPlan; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanGraphPrinter; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode; +import org.apache.iotdb.db.queryengine.plan.relational.analyzer.Field; import org.apache.iotdb.db.queryengine.plan.relational.analyzer.NodeRef; +import org.apache.iotdb.db.queryengine.plan.relational.analyzer.RelationType; import org.apache.iotdb.db.queryengine.plan.relational.planner.SymbolAllocator; import org.apache.iotdb.db.queryengine.plan.relational.planner.TableLogicalPlanner; import org.apache.iotdb.db.queryengine.plan.relational.planner.distribute.TableDistributedPlanGenerator; import org.apache.iotdb.db.queryengine.plan.relational.planner.distribute.TableDistributedPlanner; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AstVisitor; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDevice; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DescribeQuery; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Explain; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Node; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowDevice; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Table; +import org.apache.iotdb.db.queryengine.plan.relational.type.InternalTypeManager; +import org.apache.tsfile.common.conf.TSFileConfig; import org.apache.tsfile.enums.TSDataType; import org.apache.tsfile.read.common.block.TsBlock; +import org.apache.tsfile.read.common.block.TsBlockBuilder; +import org.apache.tsfile.utils.Binary; import org.apache.tsfile.utils.Pair; import java.util.ArrayList; @@ -54,6 +63,7 @@ import static org.apache.iotdb.commons.conf.IoTDBConstant.MAIN_QUERY; import static org.apache.iotdb.db.queryengine.common.header.DatasetHeader.EMPTY_HEADER; import static org.apache.iotdb.db.queryengine.execution.warnings.WarningCollector.NOOP; import static org.apache.iotdb.db.queryengine.plan.execution.memory.StatementMemorySourceVisitor.getStatementMemorySource; +import static org.apache.iotdb.db.queryengine.plan.relational.planner.node.OutputNode.buildFallbackColumnName; public class TableModelStatementMemorySourceVisitor extends AstVisitor<StatementMemorySource, TableModelStatementMemorySourceContext> { @@ -116,6 +126,38 @@ public class TableModelStatementMemorySourceVisitor return getStatementMemorySource(header, lines); } + @Override + public StatementMemorySource visitDescribeQuery( + final DescribeQuery node, final TableModelStatementMemorySourceContext context) { + final DatasetHeader datasetHeader = DatasetHeaderFactory.getDescribeQueryHeader(); + final TsBlockBuilder builder = + new TsBlockBuilder( + ColumnHeaderConstant.describeQueryColumnHeaders.stream() + .map(ColumnHeader::getColumnType) + .collect(java.util.stream.Collectors.toList())); + final RelationType outputDescriptor = + context.getAnalysis().getOutputDescriptor(node.getQuery()); + int columnNumber = 0; + for (final Field field : outputDescriptor.getVisibleFields()) { + String columnName = field.getName().orElse(null); + if (columnName == null) { + final String originColumnName = field.getOriginColumnName().orElse(null); + columnName = buildFallbackColumnName(columnNumber, originColumnName); + } + builder.getTimeColumnBuilder().writeLong(0L); + builder.getColumnBuilder(0).writeBinary(new Binary(columnName, TSFileConfig.STRING_CHARSET)); + builder + .getColumnBuilder(1) + .writeBinary( + new Binary( + InternalTypeManager.getTSDataType(field.getType()).name(), + TSFileConfig.STRING_CHARSET)); + builder.declarePosition(); + columnNumber++; + } + return new StatementMemorySource(builder.build(), datasetHeader); + } + @Override public StatementMemorySource visitShowDevice( final ShowDevice node, final TableModelStatementMemorySourceContext context) { diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java index bc6d54c37e7..c840f69a589 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java @@ -80,6 +80,7 @@ import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateView; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Delete; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DeleteDevice; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DereferenceExpression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DescribeQuery; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DescribeTable; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropColumn; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropDB; @@ -468,6 +469,12 @@ public class StatementAnalyzer { throw new SemanticException("Describe Table statement is not supported yet."); } + @Override + protected Scope visitDescribeQuery(final DescribeQuery node, final Optional<Scope> context) { + analysis.setFinishQueryAfterAnalyze(); + return visitQuery(node.getQuery(), context); + } + @Override protected Scope visitSetProperties(final SetProperties node, final Optional<Scope> context) { validateProperties(node.getProperties(), context); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TableLogicalPlanner.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TableLogicalPlanner.java index 2d7ed174d2a..840be940928 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TableLogicalPlanner.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TableLogicalPlanner.java @@ -103,7 +103,7 @@ import static org.apache.iotdb.db.queryengine.metric.QueryPlanCostMetricSet.LOGI import static org.apache.iotdb.db.queryengine.metric.QueryPlanCostMetricSet.LOGICAL_PLAN_OPTIMIZE; import static org.apache.iotdb.db.queryengine.plan.relational.metadata.MetadataUtil.createQualifiedObjectName; import static org.apache.iotdb.db.queryengine.plan.relational.planner.QueryPlanner.visibleFields; -import static org.apache.iotdb.db.queryengine.plan.relational.planner.node.OutputNode.COLUMN_NAME_PREFIX; +import static org.apache.iotdb.db.queryengine.plan.relational.planner.node.OutputNode.buildFallbackColumnName; import static org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDevice.COUNT_DEVICE_HEADER_STRING; import static org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowDevice.getDeviceColumnHeaderList; import static org.apache.iotdb.db.queryengine.plan.relational.type.InternalTypeManager.getTSDataType; @@ -341,12 +341,8 @@ public class TableLogicalPlanner { if (name == null) { String originColumnName = field.getOriginColumnName().orElse(null); - StringBuilder stringBuilder = new StringBuilder(COLUMN_NAME_PREFIX).append(columnNumber); // process of expr with Column, we record originColumnName in Field when analyze - if (originColumnName != null) { - stringBuilder.append('_').append(originColumnName); - } - name = stringBuilder.toString(); + name = buildFallbackColumnName(columnNumber, originColumnName); } names.add(name); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/OutputNode.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/OutputNode.java index d9d166e7116..ea13b2cb04f 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/OutputNode.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/OutputNode.java @@ -48,6 +48,15 @@ public class OutputNode extends SingleChildProcessNode { public static final String COLUMN_NAME_PREFIX = "_col"; + public static String buildFallbackColumnName( + final int columnNumber, final String originColumnName) { + final StringBuilder builderName = new StringBuilder(COLUMN_NAME_PREFIX).append(columnNumber); + if (originColumnName != null) { + builderName.append('_').append(originColumnName); + } + return builderName.toString(); + } + public OutputNode( PlanNodeId id, PlanNode child, List<String> columnNames, List<Symbol> outputSymbols) { super(id, child); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java index 13925ae3920..154e1d0a01a 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java @@ -449,6 +449,10 @@ public abstract class AstVisitor<R, C> { return visitStatement(node, context); } + protected R visitDescribeQuery(DescribeQuery node, C context) { + return visitStatement(node, context); + } + protected R visitSetProperties(SetProperties node, C context) { return visitStatement(node, context); } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DefaultTraversalVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DefaultTraversalVisitor.java index f22af4b020e..acd3329bdbe 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DefaultTraversalVisitor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DefaultTraversalVisitor.java @@ -92,6 +92,12 @@ public abstract class DefaultTraversalVisitor<C> extends AstVisitor<Void, C> { return null; } + @Override + protected Void visitDescribeQuery(final DescribeQuery node, final C context) { + process(node.getQuery(), context); + return null; + } + @Override protected Void visitWith(With node, C context) { for (WithQuery query : node.getQueries()) { diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DescribeQuery.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DescribeQuery.java new file mode 100644 index 00000000000..d3410852c9a --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DescribeQuery.java @@ -0,0 +1,86 @@ +/* + * 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.queryengine.plan.relational.sql.ast; + +import com.google.common.collect.ImmutableList; +import org.apache.tsfile.utils.RamUsageEstimator; + +import java.util.List; +import java.util.Objects; + +import static com.google.common.base.MoreObjects.toStringHelper; +import static java.util.Objects.requireNonNull; + +public class DescribeQuery extends Statement { + + private static final long INSTANCE_SIZE = + RamUsageEstimator.shallowSizeOfInstance(DescribeQuery.class); + + private final Query query; + + public DescribeQuery(final NodeLocation location, final Query query) { + super(requireNonNull(location, "location is null")); + this.query = requireNonNull(query, "query is null"); + } + + public Query getQuery() { + return query; + } + + @Override + public <R, C> R accept(final AstVisitor<R, C> visitor, final C context) { + return visitor.visitDescribeQuery(this, context); + } + + @Override + public List<Node> getChildren() { + return ImmutableList.of(query); + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + final DescribeQuery that = (DescribeQuery) obj; + return Objects.equals(query, that.query); + } + + @Override + public int hashCode() { + return Objects.hash(query); + } + + @Override + public String toString() { + return toStringHelper(this).add("query", query).toString(); + } + + @Override + public long ramBytesUsed() { + long size = INSTANCE_SIZE; + size += AstMemoryEstimationHelper.getEstimatedSizeOfNodeLocation(getLocationInternal()); + size += AstMemoryEstimationHelper.getEstimatedSizeOfAccountableObject(query); + return size; + } +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java index 70dc79b6adb..5f7cabf3810 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java @@ -76,6 +76,7 @@ import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Deallocate; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Delete; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DeleteDevice; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DereferenceExpression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DescribeQuery; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DescribeTable; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DoubleLiteral; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropColumn; @@ -483,6 +484,11 @@ public class AstBuilder extends RelationalSqlBaseVisitor<Node> { getLocation(ctx), getQualifiedName(ctx.table), Objects.nonNull(ctx.DETAILS()), null); } + @Override + public Node visitDescQueryStatement(final RelationalSqlParser.DescQueryStatementContext ctx) { + return new DescribeQuery(getLocation(ctx), (Query) visit(ctx.query())); + } + @Override public Node visitRenameTable(final RelationalSqlParser.RenameTableContext ctx) { return new RenameTable( diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/column/ColumnHeaderConstant.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/column/ColumnHeaderConstant.java index 33f56cdefe9..893c68a3e97 100644 --- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/column/ColumnHeaderConstant.java +++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/column/ColumnHeaderConstant.java @@ -732,6 +732,11 @@ public class ColumnHeaderConstant { new ColumnHeader(COLUMN_DATA_TYPE, TSDataType.TEXT), new ColumnHeader(COLUMN_CATEGORY, TSDataType.TEXT)); + public static final List<ColumnHeader> describeQueryColumnHeaders = + ImmutableList.of( + new ColumnHeader(COLUMN_NAME, TSDataType.TEXT), + new ColumnHeader(COLUMN_DATA_TYPE, TSDataType.TEXT)); + public static final List<ColumnHeader> describeTableDetailsColumnHeaders = ImmutableList.of( new ColumnHeader(COLUMN_NAME, TSDataType.TEXT), diff --git a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4 b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4 index 291aa1ea1ae..9e0bd09416a 100644 --- a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4 +++ b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4 @@ -58,6 +58,7 @@ statement | dropTableStatement | showTableStatement | descTableStatement + | descQueryStatement | alterTableStatement | commentStatement | showCreateTableStatement @@ -255,6 +256,10 @@ descTableStatement : (DESC | DESCRIBE) table=qualifiedName (DETAILS)? ; +descQueryStatement + : (DESC | DESCRIBE) query + ; + alterTableStatement : ALTER TABLE (IF EXISTS)? from=qualifiedName RENAME TO to=identifier #renameTable | ALTER TABLE (IF EXISTS)? tableName=qualifiedName ADD COLUMN (IF NOT EXISTS)? column=columnDefinition #addColumn
