blob: 7a37902dbb958257aa768878da3b96d27d3a9b58 [file] [log] [blame]
/*
* 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.execution.memory;
import org.apache.iotdb.common.rpc.thrift.TSchemaNode;
import org.apache.iotdb.commons.conf.IoTDBConstant;
import org.apache.iotdb.commons.exception.IllegalPathException;
import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.commons.schema.node.MNodeType;
import org.apache.iotdb.db.queryengine.common.header.ColumnHeader;
import org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant;
import org.apache.iotdb.db.queryengine.common.header.DatasetHeader;
import org.apache.iotdb.db.queryengine.plan.planner.LogicalPlanner;
import org.apache.iotdb.db.queryengine.plan.planner.distribution.DistributionPlanner;
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.statement.StatementNode;
import org.apache.iotdb.db.queryengine.plan.statement.StatementVisitor;
import org.apache.iotdb.db.queryengine.plan.statement.metadata.CountDevicesStatement;
import org.apache.iotdb.db.queryengine.plan.statement.metadata.CountNodesStatement;
import org.apache.iotdb.db.queryengine.plan.statement.metadata.CountTimeSeriesStatement;
import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowChildNodesStatement;
import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowChildPathsStatement;
import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowCurrentTimestampStatement;
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.ShowPathsUsingTemplateStatement;
import org.apache.iotdb.db.queryengine.plan.statement.sys.ExplainStatement;
import org.apache.iotdb.db.queryengine.plan.statement.sys.ShowVersionStatement;
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 java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
import static org.apache.iotdb.db.queryengine.common.header.DatasetHeader.EMPTY_HEADER;
public class StatementMemorySourceVisitor
extends StatementVisitor<StatementMemorySource, StatementMemorySourceContext> {
@Override
public StatementMemorySource visitNode(StatementNode node, StatementMemorySourceContext context) {
DatasetHeader datasetHeader = context.getAnalysis().getRespDatasetHeader();
return new StatementMemorySource(
new TsBlock(0), datasetHeader == null ? EMPTY_HEADER : datasetHeader);
}
private boolean sourceNotExist(StatementMemorySourceContext context) {
return (context.getAnalysis().getSourceExpressions() == null
|| context.getAnalysis().getSourceExpressions().isEmpty())
&& (context.getAnalysis().getDeviceToSourceExpressions() == null
|| context.getAnalysis().getDeviceToSourceExpressions().isEmpty())
&& context.getAnalysis().getDeviceTemplate() == null;
}
@Override
public StatementMemorySource visitExplain(
ExplainStatement node, StatementMemorySourceContext context) {
context.getAnalysis().setStatement(node.getQueryStatement());
DatasetHeader header =
new DatasetHeader(
Collections.singletonList(
new ColumnHeader(IoTDBConstant.COLUMN_DISTRIBUTION_PLAN, TSDataType.TEXT)),
true);
if (sourceNotExist(context)) {
return new StatementMemorySource(new TsBlock(0), header);
}
LogicalQueryPlan logicalPlan =
new LogicalPlanner(context.getQueryContext()).plan(context.getAnalysis());
DistributionPlanner planner = new DistributionPlanner(context.getAnalysis(), logicalPlan);
PlanNode rootWithExchange = planner.addExchangeNode(planner.rewriteSource());
PlanNode optimizedRootWithExchange = planner.optimize(rootWithExchange);
List<String> lines =
optimizedRootWithExchange.accept(
new PlanGraphPrinter(),
new PlanGraphPrinter.GraphContext(
context.getQueryContext().getTypeProvider().getTemplatedInfo()));
TsBlockBuilder builder = new TsBlockBuilder(Collections.singletonList(TSDataType.TEXT));
lines.forEach(
line -> {
builder.getTimeColumnBuilder().writeLong(0L);
builder.getColumnBuilder(0).writeBinary(new Binary(line, TSFileConfig.STRING_CHARSET));
builder.declarePosition();
});
TsBlock tsBlock = builder.build();
return new StatementMemorySource(tsBlock, header);
}
@Override
public StatementMemorySource visitShowChildPaths(
ShowChildPathsStatement showChildPathsStatement, StatementMemorySourceContext context) {
List<TSDataType> outputDataTypes =
ColumnHeaderConstant.showChildPathsColumnHeaders.stream()
.map(ColumnHeader::getColumnType)
.collect(Collectors.toList());
TsBlockBuilder tsBlockBuilder = new TsBlockBuilder(outputDataTypes);
Set<TSchemaNode> matchedChildPaths = context.getAnalysis().getMatchedNodes();
// sort by node type
Set<TSchemaNode> sortSet =
new TreeSet<>(
(o1, o2) -> {
if (o1.getNodeType() == o2.getNodeType()) {
return o1.getNodeName().compareTo(o2.getNodeName());
}
return o1.getNodeType() - o2.getNodeType();
});
sortSet.addAll(matchedChildPaths);
sortSet.forEach(
node -> {
tsBlockBuilder.getTimeColumnBuilder().writeLong(0L);
tsBlockBuilder
.getColumnBuilder(0)
.writeBinary(new Binary(node.getNodeName(), TSFileConfig.STRING_CHARSET));
tsBlockBuilder
.getColumnBuilder(1)
.writeBinary(
new Binary(
MNodeType.getMNodeType(node.getNodeType()).getNodeTypeName(),
TSFileConfig.STRING_CHARSET));
tsBlockBuilder.declarePosition();
});
return new StatementMemorySource(
tsBlockBuilder.build(), context.getAnalysis().getRespDatasetHeader());
}
@Override
public StatementMemorySource visitShowChildNodes(
ShowChildNodesStatement showChildNodesStatement, StatementMemorySourceContext context) {
List<TSDataType> outputDataTypes =
ColumnHeaderConstant.showChildNodesColumnHeaders.stream()
.map(ColumnHeader::getColumnType)
.collect(Collectors.toList());
TsBlockBuilder tsBlockBuilder = new TsBlockBuilder(outputDataTypes);
Set<String> matchedChildNodes =
context.getAnalysis().getMatchedNodes().stream()
.map(TSchemaNode::getNodeName)
.collect(Collectors.toCollection(TreeSet::new));
matchedChildNodes.forEach(
node -> {
try {
PartialPath nodePath = new PartialPath(node);
String nodeName = nodePath.getTailNode();
tsBlockBuilder.getTimeColumnBuilder().writeLong(0L);
tsBlockBuilder
.getColumnBuilder(0)
.writeBinary(new Binary(nodeName, TSFileConfig.STRING_CHARSET));
tsBlockBuilder.declarePosition();
} catch (IllegalPathException ignored) {
// definitely won't happen
}
});
return new StatementMemorySource(
tsBlockBuilder.build(), context.getAnalysis().getRespDatasetHeader());
}
@Override
public StatementMemorySource visitShowVersion(
ShowVersionStatement showVersionStatement, StatementMemorySourceContext context) {
List<TSDataType> outputDataTypes =
ColumnHeaderConstant.showVersionColumnHeaders.stream()
.map(ColumnHeader::getColumnType)
.collect(Collectors.toList());
TsBlockBuilder tsBlockBuilder = new TsBlockBuilder(outputDataTypes);
tsBlockBuilder.getTimeColumnBuilder().writeLong(0L);
tsBlockBuilder
.getColumnBuilder(0)
.writeBinary(new Binary(IoTDBConstant.VERSION, TSFileConfig.STRING_CHARSET));
tsBlockBuilder
.getColumnBuilder(1)
.writeBinary(new Binary(IoTDBConstant.BUILD_INFO, TSFileConfig.STRING_CHARSET));
tsBlockBuilder.declarePosition();
return new StatementMemorySource(
tsBlockBuilder.build(), context.getAnalysis().getRespDatasetHeader());
}
@Override
public StatementMemorySource visitCountNodes(
CountNodesStatement countStatement, StatementMemorySourceContext context) {
List<TSDataType> outputDataTypes =
ColumnHeaderConstant.countNodesColumnHeaders.stream()
.map(ColumnHeader::getColumnType)
.collect(Collectors.toList());
TsBlockBuilder tsBlockBuilder = new TsBlockBuilder(outputDataTypes);
Set<String> matchedChildNodes =
context.getAnalysis().getMatchedNodes().stream()
.map(TSchemaNode::getNodeName)
.collect(Collectors.toSet());
tsBlockBuilder.getTimeColumnBuilder().writeLong(0L);
tsBlockBuilder.getColumnBuilder(0).writeLong(matchedChildNodes.size());
tsBlockBuilder.declarePosition();
return new StatementMemorySource(
tsBlockBuilder.build(), context.getAnalysis().getRespDatasetHeader());
}
@Override
public StatementMemorySource visitCountDevices(
CountDevicesStatement countStatement, StatementMemorySourceContext context) {
List<TSDataType> outputDataTypes =
ColumnHeaderConstant.countDevicesColumnHeaders.stream()
.map(ColumnHeader::getColumnType)
.collect(Collectors.toList());
TsBlockBuilder tsBlockBuilder = new TsBlockBuilder(outputDataTypes);
tsBlockBuilder.getTimeColumnBuilder().writeLong(0L);
tsBlockBuilder.getColumnBuilder(0).writeLong(0);
tsBlockBuilder.declarePosition();
return new StatementMemorySource(
tsBlockBuilder.build(), context.getAnalysis().getRespDatasetHeader());
}
@Override
public StatementMemorySource visitCountTimeSeries(
CountTimeSeriesStatement countStatement, StatementMemorySourceContext context) {
List<TSDataType> outputDataTypes =
ColumnHeaderConstant.countTimeSeriesColumnHeaders.stream()
.map(ColumnHeader::getColumnType)
.collect(Collectors.toList());
TsBlockBuilder tsBlockBuilder = new TsBlockBuilder(outputDataTypes);
tsBlockBuilder.getTimeColumnBuilder().writeLong(0L);
tsBlockBuilder.getColumnBuilder(0).writeLong(0);
tsBlockBuilder.declarePosition();
return new StatementMemorySource(
tsBlockBuilder.build(), context.getAnalysis().getRespDatasetHeader());
}
@Override
public StatementMemorySource visitShowPathsUsingTemplate(
ShowPathsUsingTemplateStatement showPathsUsingTemplateStatement,
StatementMemorySourceContext context) {
List<TSDataType> outputDataTypes =
ColumnHeaderConstant.showPathsUsingTemplateHeaders.stream()
.map(ColumnHeader::getColumnType)
.collect(Collectors.toList());
TsBlockBuilder tsBlockBuilder = new TsBlockBuilder(outputDataTypes);
return new StatementMemorySource(
tsBlockBuilder.build(), context.getAnalysis().getRespDatasetHeader());
}
public StatementMemorySource visitShowCurrentTimestamp(
ShowCurrentTimestampStatement showCurrentTimestampStatement,
StatementMemorySourceContext context) {
List<TSDataType> outputDataTypes =
ColumnHeaderConstant.showCurrentTimestampColumnHeaders.stream()
.map(ColumnHeader::getColumnType)
.collect(Collectors.toList());
TsBlockBuilder tsBlockBuilder = new TsBlockBuilder(outputDataTypes);
tsBlockBuilder.getTimeColumnBuilder().writeLong(0L);
tsBlockBuilder.getColumnBuilder(0).writeLong(System.currentTimeMillis());
tsBlockBuilder.declarePosition();
return new StatementMemorySource(
tsBlockBuilder.build(), context.getAnalysis().getRespDatasetHeader());
}
}