Skip to content

Commit 92eb32c

Browse files
feat(table-model): implement DESCRIBE QUERY for relational metadata extraction
1 parent 24b963a commit 92eb32c

7 files changed

Lines changed: 168 additions & 1 deletion

File tree

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/QueryExecution.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ private ExecutionResult retry() {
252252
}
253253

254254
private boolean skipExecute() {
255-
return analysis.canSkipExecute(context);
255+
return analysis.isFailed() || analysis.isFinishQueryAfterAnalyze();
256256
}
257257

258258
private void constructResultForMemorySource() {

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceVisitor.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,61 @@ public StatementMemorySource visitCountDevice(
130130
node.getTsBlock(context.getAnalysis()), node.getDataSetHeader());
131131
}
132132

133+
@Override
134+
public StatementMemorySource visitDescribeQuery(
135+
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DescribeQuery node,
136+
TableModelStatementMemorySourceContext context) {
137+
138+
java.util.List<org.apache.iotdb.commons.schema.column.ColumnHeader> columnHeaders =
139+
new java.util.ArrayList<>();
140+
columnHeaders.add(
141+
new org.apache.iotdb.commons.schema.column.ColumnHeader(
142+
"Column", org.apache.tsfile.enums.TSDataType.TEXT));
143+
columnHeaders.add(
144+
new org.apache.iotdb.commons.schema.column.ColumnHeader(
145+
"Type", org.apache.tsfile.enums.TSDataType.TEXT));
146+
147+
org.apache.iotdb.db.queryengine.common.header.DatasetHeader datasetHeader =
148+
new org.apache.iotdb.db.queryengine.common.header.DatasetHeader(columnHeaders, true);
149+
150+
java.util.List<String> columnNames = new java.util.ArrayList<>();
151+
java.util.List<String> columnTypes = new java.util.ArrayList<>();
152+
153+
context
154+
.getAnalysis()
155+
.getOutputDescriptor()
156+
.getVisibleFields()
157+
.forEach(
158+
field -> {
159+
columnNames.add(field.getName().orElse("unknown"));
160+
columnTypes.add(field.getType().toString());
161+
});
162+
163+
org.apache.tsfile.read.common.block.TsBlockBuilder builder =
164+
new org.apache.tsfile.read.common.block.TsBlockBuilder(
165+
java.util.Arrays.asList(
166+
org.apache.tsfile.enums.TSDataType.TEXT, org.apache.tsfile.enums.TSDataType.TEXT));
167+
168+
for (int i = 0; i < columnNames.size(); i++) {
169+
builder.getTimeColumnBuilder().writeLong(0);
170+
171+
builder
172+
.getColumnBuilder(0)
173+
.writeBinary(
174+
new org.apache.tsfile.utils.Binary(
175+
columnNames.get(i).getBytes(java.nio.charset.StandardCharsets.UTF_8)));
176+
builder
177+
.getColumnBuilder(1)
178+
.writeBinary(
179+
new org.apache.tsfile.utils.Binary(
180+
columnTypes.get(i).getBytes(java.nio.charset.StandardCharsets.UTF_8)));
181+
182+
builder.declarePosition();
183+
}
184+
185+
return new StatementMemorySource(builder.build(), datasetHeader);
186+
}
187+
133188
private List<String> mergeExplainResults(
134189
Map<NodeRef<Table>, Pair<Integer, List<String>>> cteExplainResults,
135190
List<String> mainExplainResult) {

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analysis.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ public class Analysis implements IAnalysis {
257257
private boolean emptyDataSource = false;
258258

259259
private boolean isQuery = false;
260+
private boolean isDescribe = false;
260261

261262
// SqlParser is needed during query planning phase for executing uncorrelated scalar subqueries
262263
// in advance (predicate folding). The planner needs to parse and execute these subqueries
@@ -1552,6 +1553,14 @@ public void setInsert(Insert insert) {
15521553
this.insert = insert;
15531554
}
15541555

1556+
public void setDescribe(boolean isDescribe) {
1557+
this.isDescribe = isDescribe;
1558+
}
1559+
1560+
public boolean isDescribe() {
1561+
return isDescribe;
1562+
}
1563+
15551564
public Insert getInsert() {
15561565
return insert;
15571566
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Delete;
8181
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DeleteDevice;
8282
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DereferenceExpression;
83+
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DescribeQuery;
8384
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DescribeTable;
8485
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropColumn;
8586
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropDB;
@@ -850,6 +851,22 @@ protected Scope visitExplain(Explain node, Optional<Scope> context) {
850851
return visitQuery((Query) node.getStatement(), context);
851852
}
852853

854+
@Override
855+
protected Scope visitDescribeQuery(DescribeQuery node, Optional<Scope> context) {
856+
analysis.setFinishQueryAfterAnalyze(true);
857+
Scope scope = visitQuery(node.getQuery(), context);
858+
859+
RelationType outputDescriptor = analysis.getOutputDescriptor();
860+
for (Field field : outputDescriptor.getVisibleFields()) {
861+
String name = field.getName().orElse("unknown");
862+
String type = field.getType().toString();
863+
System.out.println("DESCRIBE_DEBUG: Column=" + name + ", Type=" + type);
864+
}
865+
866+
analysis.setDescribe(true);
867+
return scope;
868+
}
869+
853870
@Override
854871
protected Scope visitExplainAnalyze(ExplainAnalyze node, Optional<Scope> context) {
855872
queryContext.setExplainType(ExplainType.EXPLAIN_ANALYZE);

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,10 @@ protected R visitDescribeTable(DescribeTable node, C context) {
449449
return visitStatement(node, context);
450450
}
451451

452+
protected R visitDescribeQuery(DescribeQuery node, C context) {
453+
return visitStatement(node, context);
454+
}
455+
452456
protected R visitSetProperties(SetProperties node, C context) {
453457
return visitStatement(node, context);
454458
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.iotdb.db.queryengine.plan.relational.sql.ast;
21+
22+
import com.google.common.collect.ImmutableList;
23+
import org.apache.tsfile.utils.RamUsageEstimator;
24+
25+
import java.util.List;
26+
import java.util.Objects;
27+
28+
import static java.util.Objects.requireNonNull;
29+
30+
public class DescribeQuery extends Statement {
31+
32+
private static final long INSTANCE_SIZE =
33+
RamUsageEstimator.shallowSizeOfInstance(DescribeQuery.class);
34+
35+
private final Query query;
36+
37+
public DescribeQuery(NodeLocation location, Query query) {
38+
super(requireNonNull(location, "location is null"));
39+
this.query = requireNonNull(query, "query is null");
40+
}
41+
42+
public Query getQuery() {
43+
return query;
44+
}
45+
46+
@Override
47+
public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
48+
return visitor.visitDescribeQuery(this, context);
49+
}
50+
51+
@Override
52+
public List<Node> getChildren() {
53+
return ImmutableList.of(query);
54+
}
55+
56+
@Override
57+
public boolean equals(Object obj) {
58+
if (this == obj) return true;
59+
if (obj == null || getClass() != obj.getClass()) return false;
60+
DescribeQuery that = (DescribeQuery) obj;
61+
return Objects.equals(query, that.query);
62+
}
63+
64+
@Override
65+
public int hashCode() {
66+
return Objects.hash(query);
67+
}
68+
69+
@Override
70+
public String toString() {
71+
return "DescribeQuery{" + "query=" + query + '}';
72+
}
73+
74+
@Override
75+
public long ramBytesUsed() {
76+
long size = INSTANCE_SIZE;
77+
size += AstMemoryEstimationHelper.getEstimatedSizeOfNodeLocation(getLocationInternal());
78+
size += AstMemoryEstimationHelper.getEstimatedSizeOfAccountableObject(query);
79+
return size;
80+
}
81+
}

iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,7 @@ queryStatement
914914
: query #statementDefault
915915
| EXPLAIN query #explain
916916
| EXPLAIN ANALYZE VERBOSE? query #explainAnalyze
917+
| DESCRIBE QUERY query #describeQuery
917918
;
918919

919920
query

0 commit comments

Comments
 (0)