This is an automated email from the ASF dual-hosted git repository. caogaofei pushed a commit to branch beyyes/TableModelGrammar0624 in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 937b699fed73cef84843d0d62939c3ed9898e8b1 Author: Beyyes <[email protected]> AuthorDate: Mon Jun 24 17:13:02 2024 +0800 perfect the usage of QualifiedObjectName in TableScan, perfect the getDataPartition interface in Metadata, perfect the FilterScanCombine rule --- .../plan/planner/plan/node/PlanGraphPrinter.java | 2 +- .../plan/relational/metadata/Metadata.java | 23 ++- .../relational/metadata/QualifiedObjectName.java | 2 + .../relational/metadata/TableMetadataImpl.java | 20 ++- .../plan/relational/planner/RelationPlanner.java | 9 +- .../relational/planner/node/TableScanNode.java | 51 ++++-- .../planner/optimizations/FilterScanCombine.java | 82 ++++----- .../planner/optimizations/IndexScan.java | 184 ++++++--------------- .../plan/relational/sql/ast/QualifiedName.java | 2 +- .../plan/relational/analyzer/AnalyzerTest.java | 6 +- .../plan/relational/analyzer/TestMatadata.java | 20 ++- 11 files changed, 196 insertions(+), 205 deletions(-) diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java index 7f94c4ba316..5052c27453d 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java @@ -604,7 +604,7 @@ public class PlanGraphPrinter extends PlanVisitor<List<String>, PlanGraphPrinter public List<String> visitTableScan(TableScanNode node, GraphContext context) { List<String> boxValue = new ArrayList<>(); boxValue.add(String.format("TableScan-%s", node.getPlanNodeId().getId())); - boxValue.add(String.format("QualifiedTableName: %s", node.getQualifiedTableName())); + boxValue.add(String.format("QualifiedTableName: %s", node.getQualifiedObjectName())); boxValue.add(String.format("OutputSymbols: %s", node.getOutputSymbols())); boxValue.add(String.format("DeviceEntriesSize: %s", node.getDeviceEntries().size())); boxValue.add(String.format("ScanOrder: %s", node.getScanOrder())); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/Metadata.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/Metadata.java index 8e7fddf677d..696e4628d2d 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/Metadata.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/Metadata.java @@ -19,10 +19,11 @@ package org.apache.iotdb.db.queryengine.plan.relational.metadata; +import org.apache.iotdb.commons.partition.DataPartition; +import org.apache.iotdb.commons.partition.DataPartitionQueryParam; import org.apache.iotdb.commons.partition.SchemaPartition; import org.apache.iotdb.db.queryengine.common.MPPQueryContext; import org.apache.iotdb.db.queryengine.common.SessionInfo; -import org.apache.iotdb.db.queryengine.plan.analyze.IPartitionFetcher; import org.apache.iotdb.db.queryengine.plan.relational.function.OperatorType; import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression; @@ -33,6 +34,7 @@ import org.apache.tsfile.file.metadata.IDeviceID; import org.apache.tsfile.read.common.type.Type; import java.util.List; +import java.util.Map; import java.util.Optional; public interface Metadata { @@ -59,8 +61,6 @@ public interface Metadata { boolean canCoerce(Type from, Type to); - IPartitionFetcher getPartitionFetcher(); - /** * get all device ids and corresponding attributes from schema region * @@ -132,4 +132,21 @@ public interface Metadata { * <p>The device id shall be [table, seg1, ....] */ SchemaPartition getSchemaPartition(String database); + + // ======================== Table Model Data Partition Interface ======================== + /** + * Get data partition, used in query scenarios. + * + * @param sgNameToQueryParamsMap database name -> the list of DataPartitionQueryParams + */ + DataPartition getDataPartition(Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap); + + /** + * Get data partition, used in query scenarios which contains time filter like: time < XX or time + * > XX + * + * @return sgNameToQueryParamsMap database name -> the list of DataPartitionQueryParams + */ + DataPartition getDataPartitionWithUnclosedTimeRange( + Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap); } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/QualifiedObjectName.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/QualifiedObjectName.java index 834170b27d6..76446cdf648 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/QualifiedObjectName.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/QualifiedObjectName.java @@ -45,6 +45,8 @@ public class QualifiedObjectName { } private final String dbName; + + // objectName represents tableName private final String objectName; public QualifiedObjectName(String dbName, String objectName) { diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java index 7ca601f13ec..883b79b66f6 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java @@ -19,6 +19,8 @@ package org.apache.iotdb.db.queryengine.plan.relational.metadata; +import org.apache.iotdb.commons.partition.DataPartition; +import org.apache.iotdb.commons.partition.DataPartitionQueryParam; import org.apache.iotdb.commons.partition.SchemaPartition; import org.apache.iotdb.commons.udf.builtin.BuiltinAggregationFunction; import org.apache.iotdb.commons.udf.builtin.BuiltinScalarFunction; @@ -44,6 +46,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Optional; import static org.apache.iotdb.commons.conf.IoTDBConstant.PATH_ROOT; @@ -269,11 +272,6 @@ public class TableMetadataImpl implements Metadata { return true; } - @Override - public IPartitionFetcher getPartitionFetcher() { - return ClusterPartitionFetcher.getInstance(); - } - @Override public List<DeviceEntry> indexScan( QualifiedObjectName tableName, @@ -317,6 +315,18 @@ public class TableMetadataImpl implements Metadata { return partitionFetcher.getSchemaPartition(PATH_ROOT + PATH_SEPARATOR + database); } + @Override + public DataPartition getDataPartition( + Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap) { + return partitionFetcher.getDataPartition(sgNameToQueryParamsMap); + } + + @Override + public DataPartition getDataPartitionWithUnclosedTimeRange( + Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap) { + return partitionFetcher.getDataPartitionWithUnclosedTimeRange(sgNameToQueryParamsMap); + } + public static boolean isTwoNumericType(List<? extends Type> argumentTypes) { return argumentTypes.size() == 2 && isNumericType(argumentTypes.get(0)) diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/RelationPlanner.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/RelationPlanner.java index c0386bcbbb2..ceecc22b67d 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/RelationPlanner.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/RelationPlanner.java @@ -21,6 +21,7 @@ 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.Scope; import org.apache.iotdb.db.queryengine.plan.relational.metadata.ColumnSchema; +import org.apache.iotdb.db.queryengine.plan.relational.metadata.QualifiedObjectName; import org.apache.iotdb.db.queryengine.plan.relational.planner.node.TableScanNode; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AliasedRelation; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AstVisitor; @@ -28,6 +29,7 @@ import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Except; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Intersect; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Join; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Node; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.QualifiedName; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Query; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.QuerySpecification; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SubqueryExpression; @@ -107,10 +109,15 @@ public class RelationPlanner extends AstVisitor<RelationPlan, Void> { } List<Symbol> outputSymbols = outputSymbolsBuilder.build(); + QualifiedName qualifiedName = analysis.getRelationName(table); TableScanNode tableScanNode = new TableScanNode( idAllocator.genPlanNodeId(), - table.getName().toString(), + new QualifiedObjectName( + qualifiedName.getPrefix().isPresent() + ? qualifiedName.getPrefix().get().toString() + : null, + qualifiedName.getSuffix()), outputSymbols, symbolToColumnSchema.build()); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/TableScanNode.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/TableScanNode.java index a20decfe57c..ebb4fb5b6c2 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/TableScanNode.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/TableScanNode.java @@ -22,6 +22,7 @@ import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanVisitor; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.source.SourceNode; import org.apache.iotdb.db.queryengine.plan.relational.metadata.ColumnSchema; import org.apache.iotdb.db.queryengine.plan.relational.metadata.DeviceEntry; +import org.apache.iotdb.db.queryengine.plan.relational.metadata.QualifiedObjectName; import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression; import org.apache.iotdb.db.queryengine.plan.statement.component.Ordering; @@ -43,8 +44,7 @@ import java.util.stream.Collectors; public class TableScanNode extends SourceNode { - // db.tablename - private final String qualifiedTableName; + private final QualifiedObjectName qualifiedObjectName; private List<Symbol> outputSymbols; private Map<Symbol, ColumnSchema> assignments; @@ -74,18 +74,18 @@ public class TableScanNode extends SourceNode { public TableScanNode( PlanNodeId id, - String qualifiedTableName, + QualifiedObjectName qualifiedObjectName, List<Symbol> outputSymbols, Map<Symbol, ColumnSchema> assignments) { super(id); - this.qualifiedTableName = qualifiedTableName; + this.qualifiedObjectName = qualifiedObjectName; this.outputSymbols = outputSymbols; this.assignments = assignments; } public TableScanNode( PlanNodeId id, - String qualifiedTableName, + QualifiedObjectName qualifiedObjectName, List<Symbol> outputSymbols, Map<Symbol, ColumnSchema> assignments, List<DeviceEntry> deviceEntries, @@ -93,7 +93,7 @@ public class TableScanNode extends SourceNode { Ordering scanOrder, Expression pushDownPredicate) { super(id); - this.qualifiedTableName = qualifiedTableName; + this.qualifiedObjectName = qualifiedObjectName; this.outputSymbols = outputSymbols; this.assignments = assignments; this.deviceEntries = deviceEntries; @@ -119,7 +119,7 @@ public class TableScanNode extends SourceNode { public TableScanNode clone() { return new TableScanNode( getPlanNodeId(), - qualifiedTableName, + qualifiedObjectName, outputSymbols, assignments, deviceEntries, @@ -141,7 +141,14 @@ public class TableScanNode extends SourceNode { @Override protected void serializeAttributes(ByteBuffer byteBuffer) { PlanNodeType.TABLE_SCAN_NODE.serialize(byteBuffer); - ReadWriteIOUtils.write(qualifiedTableName, byteBuffer); + + if (qualifiedObjectName.getDatabaseName() != null) { + ReadWriteIOUtils.write(true, byteBuffer); + ReadWriteIOUtils.write(qualifiedObjectName.getDatabaseName(), byteBuffer); + } else { + ReadWriteIOUtils.write(false, byteBuffer); + } + ReadWriteIOUtils.write(qualifiedObjectName.getObjectName(), byteBuffer); ReadWriteIOUtils.write(outputSymbols.size(), byteBuffer); outputSymbols.forEach(symbol -> ReadWriteIOUtils.write(symbol.getName(), byteBuffer)); @@ -176,7 +183,13 @@ public class TableScanNode extends SourceNode { @Override protected void serializeAttributes(DataOutputStream stream) throws IOException { PlanNodeType.TABLE_SCAN_NODE.serialize(stream); - ReadWriteIOUtils.write(qualifiedTableName, stream); + if (qualifiedObjectName.getDatabaseName() != null) { + ReadWriteIOUtils.write(true, stream); + ReadWriteIOUtils.write(qualifiedObjectName.getDatabaseName(), stream); + } else { + ReadWriteIOUtils.write(false, stream); + } + ReadWriteIOUtils.write(qualifiedObjectName.getObjectName(), stream); ReadWriteIOUtils.write(outputSymbols.size(), stream); for (Symbol symbol : outputSymbols) { @@ -211,9 +224,15 @@ public class TableScanNode extends SourceNode { } public static TableScanNode deserialize(ByteBuffer byteBuffer) { - String qualifiedTableName = ReadWriteIOUtils.readString(byteBuffer); - int size = ReadWriteIOUtils.readInt(byteBuffer); + boolean hasDatabaseName = ReadWriteIOUtils.readBool(byteBuffer); + String databaseName = null; + if (hasDatabaseName) { + databaseName = ReadWriteIOUtils.readString(byteBuffer); + } + String tableName = ReadWriteIOUtils.readString(byteBuffer); + QualifiedObjectName qualifiedObjectName = new QualifiedObjectName(databaseName, tableName); + int size = ReadWriteIOUtils.readInt(byteBuffer); List<Symbol> outputSymbols = new ArrayList<>(size); for (int i = 0; i < size; i++) { outputSymbols.add(Symbol.deserialize(byteBuffer)); @@ -250,7 +269,7 @@ public class TableScanNode extends SourceNode { return new TableScanNode( planNodeId, - qualifiedTableName, + qualifiedObjectName, outputSymbols, assignments, deviceEntries, @@ -282,18 +301,18 @@ public class TableScanNode extends SourceNode { return false; } TableScanNode that = (TableScanNode) o; - return Objects.equals(qualifiedTableName, that.qualifiedTableName) + return Objects.equals(qualifiedObjectName, that.qualifiedObjectName) && Objects.equals(outputSymbols, that.outputSymbols) && Objects.equals(regionReplicaSet, that.regionReplicaSet); } @Override public int hashCode() { - return Objects.hash(super.hashCode(), qualifiedTableName, outputSymbols, regionReplicaSet); + return Objects.hash(super.hashCode(), qualifiedObjectName, outputSymbols, regionReplicaSet); } - public String getQualifiedTableName() { - return this.qualifiedTableName; + public QualifiedObjectName getQualifiedObjectName() { + return this.qualifiedObjectName; } public void setOutputSymbols(List<Symbol> outputSymbols) { diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/FilterScanCombine.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/FilterScanCombine.java index 3015f88ce60..02236cfc4b5 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/FilterScanCombine.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/FilterScanCombine.java @@ -148,52 +148,54 @@ public class FilterScanCombine implements RelationalPlanOptimizer { return node; } - } - private static List<List<Expression>> splitConjunctionExpressions( - RewriterContext context, TableScanNode node) { - Expression predicate = context.pushDownPredicate; - - Set<String> idOrAttributeColumnNames = - node.getIdAndAttributeIndexMap().keySet().stream() - .map(Symbol::getName) - .collect(Collectors.toSet()); - - Set<String> measurementColumnNames = - node.getAssignments().entrySet().stream() - .filter(e -> MEASUREMENT.equals(e.getValue().getColumnCategory())) - .map(e -> e.getKey().getName()) - .collect(Collectors.toSet()); - - List<Expression> metadataExpressions = new ArrayList<>(); - List<Expression> expressionsCanPushDown = new ArrayList<>(); - List<Expression> expressionsCannotPushDown = new ArrayList<>(); - - if (predicate instanceof LogicalExpression - && ((LogicalExpression) predicate).getOperator() == LogicalExpression.Operator.AND) { - - for (Expression expression : ((LogicalExpression) predicate).getTerms()) { - if (PredicatePushIntoMetadataChecker.check(idOrAttributeColumnNames, expression)) { - metadataExpressions.add(expression); - } else if (PredicateCombineIntoTableScanChecker.check(measurementColumnNames, expression)) { - expressionsCanPushDown.add(expression); - } else { - expressionsCannotPushDown.add(expression); + private List<List<Expression>> splitConjunctionExpressions( + RewriterContext context, TableScanNode node) { + Expression predicate = context.pushDownPredicate; + + Set<String> idOrAttributeColumnNames = + node.getIdAndAttributeIndexMap().keySet().stream() + .map(Symbol::getName) + .collect(Collectors.toSet()); + + Set<String> measurementColumnNames = + node.getAssignments().entrySet().stream() + .filter(e -> MEASUREMENT.equals(e.getValue().getColumnCategory())) + .map(e -> e.getKey().getName()) + .collect(Collectors.toSet()); + + List<Expression> metadataExpressions = new ArrayList<>(); + List<Expression> expressionsCanPushDown = new ArrayList<>(); + List<Expression> expressionsCannotPushDown = new ArrayList<>(); + + if (predicate instanceof LogicalExpression + && ((LogicalExpression) predicate).getOperator() == LogicalExpression.Operator.AND) { + + for (Expression expression : ((LogicalExpression) predicate).getTerms()) { + if (PredicatePushIntoMetadataChecker.check(idOrAttributeColumnNames, expression)) { + metadataExpressions.add(expression); + } else if (PredicateCombineIntoTableScanChecker.check( + measurementColumnNames, expression)) { + expressionsCanPushDown.add(expression); + } else { + expressionsCannotPushDown.add(expression); + } } + + return Arrays.asList( + metadataExpressions, expressionsCanPushDown, expressionsCannotPushDown); } - return Arrays.asList(metadataExpressions, expressionsCanPushDown, expressionsCannotPushDown); - } + if (PredicatePushIntoMetadataChecker.check(idOrAttributeColumnNames, predicate)) { + metadataExpressions.add(predicate); + } else if (PredicateCombineIntoTableScanChecker.check(measurementColumnNames, predicate)) { + expressionsCanPushDown.add(predicate); + } else { + expressionsCannotPushDown.add(predicate); + } - if (PredicatePushIntoMetadataChecker.check(idOrAttributeColumnNames, predicate)) { - metadataExpressions.add(predicate); - } else if (PredicateCombineIntoTableScanChecker.check(measurementColumnNames, predicate)) { - expressionsCanPushDown.add(predicate); - } else { - expressionsCannotPushDown.add(predicate); + return Arrays.asList(metadataExpressions, expressionsCanPushDown, expressionsCannotPushDown); } - - return Arrays.asList(metadataExpressions, expressionsCanPushDown, expressionsCannotPushDown); } static boolean containsDiffFunction(Expression expression) { diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/IndexScan.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/IndexScan.java index ab337c3c30f..a2a0e725d6b 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/IndexScan.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/IndexScan.java @@ -23,15 +23,12 @@ import org.apache.iotdb.db.conf.IoTDBConfig; import org.apache.iotdb.db.conf.IoTDBDescriptor; import org.apache.iotdb.db.queryengine.common.MPPQueryContext; import org.apache.iotdb.db.queryengine.common.SessionInfo; -import org.apache.iotdb.db.queryengine.plan.analyze.IPartitionFetcher; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanVisitor; import org.apache.iotdb.db.queryengine.plan.relational.analyzer.Analysis; import org.apache.iotdb.db.queryengine.plan.relational.metadata.DeviceEntry; import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata; -import org.apache.iotdb.db.queryengine.plan.relational.metadata.QualifiedObjectName; import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol; -import org.apache.iotdb.db.queryengine.plan.relational.planner.node.FilterNode; import org.apache.iotdb.db.queryengine.plan.relational.planner.node.TableScanNode; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression; @@ -40,7 +37,6 @@ import org.apache.tsfile.utils.Pair; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -53,7 +49,7 @@ import static org.apache.iotdb.db.queryengine.plan.analyze.AnalyzeVisitor.getTim /** Extract IDeviceID */ public class IndexScan implements RelationalPlanOptimizer { - static final IoTDBConfig CONFIG = IoTDBDescriptor.getInstance().getConfig(); + private static final IoTDBConfig CONFIG = IoTDBDescriptor.getInstance().getConfig(); @Override public PlanNode optimize( @@ -62,15 +58,29 @@ public class IndexScan implements RelationalPlanOptimizer { Metadata metadata, SessionInfo sessionInfo, MPPQueryContext queryContext) { - - return planNode.accept( - new Rewriter(), new RewriterContext(null, metadata, sessionInfo, analysis, queryContext)); + return planNode.accept(new Rewriter(metadata, sessionInfo, analysis, queryContext), null); } - private static class Rewriter extends PlanVisitor<PlanNode, RewriterContext> { + private static class Rewriter extends PlanVisitor<PlanNode, Void> { + + private final Metadata metadata; + private final SessionInfo sessionInfo; + private final Analysis analysis; + private final MPPQueryContext queryContext; + + Rewriter( + Metadata metadata, + SessionInfo sessionInfo, + Analysis analysis, + MPPQueryContext queryContext) { + this.metadata = metadata; + this.sessionInfo = sessionInfo; + this.analysis = analysis; + this.queryContext = queryContext; + } @Override - public PlanNode visitPlan(PlanNode node, RewriterContext context) { + public PlanNode visitPlan(PlanNode node, Void context) { for (PlanNode child : node.getChildren()) { child.accept(this, context); } @@ -78,27 +88,12 @@ public class IndexScan implements RelationalPlanOptimizer { } @Override - public PlanNode visitFilter(FilterNode node, RewriterContext context) { - context.setPredicate(node.getPredicate()); - context.setFilterNode(node); - node.getChild().accept(this, context); - return node; - } - - @Override - public PlanNode visitTableScan(TableScanNode node, RewriterContext context) { - - // only when exist diff predicate in FilterNode, context.predicate will not equal null - if (context.predicate == null) { - context.predicate = node.getPushDownPredicate(); - } - + public PlanNode visitTableScan(TableScanNode node, Void context) { List<Expression> metadataExpressions = - context.queryContext.getTableModelPredicateExpressions() == null - || context.queryContext.getTableModelPredicateExpressions().get(0).isEmpty() + queryContext.getTableModelPredicateExpressions() == null + || queryContext.getTableModelPredicateExpressions().get(0).isEmpty() ? Collections.emptyList() - : context.queryContext.getTableModelPredicateExpressions().get(0); - String dbName = context.getSessionInfo().getDatabaseName().get(); + : queryContext.getTableModelPredicateExpressions().get(0); List<String> attributeColumns = node.getOutputSymbols().stream() .filter( @@ -106,25 +101,16 @@ public class IndexScan implements RelationalPlanOptimizer { .map(Symbol::getName) .collect(Collectors.toList()); List<DeviceEntry> deviceEntries = - context - .getMetadata() - .indexScan( - new QualifiedObjectName(dbName, node.getQualifiedTableName()), - metadataExpressions, - attributeColumns); + metadata.indexScan(node.getQualifiedObjectName(), metadataExpressions, attributeColumns); node.setDeviceEntries(deviceEntries); if (deviceEntries.isEmpty()) { - context.getAnalysis().setFinishQueryAfterAnalyze(); + analysis.setFinishQueryAfterAnalyze(); } else { - String treeModelDatabase = "root." + dbName; + String treeModelDatabase = "root." + node.getQualifiedObjectName().getDatabaseName(); DataPartition dataPartition = fetchDataPartitionByDevices( - deviceEntries, - treeModelDatabase, - context.getQueryContext().getGlobalTimeFilter(), - context.getMetadata().getPartitionFetcher(), - context.getQueryContext()); - context.getAnalysis().setDataPartition(dataPartition); + deviceEntries, treeModelDatabase, queryContext.getGlobalTimeFilter()); + analysis.setDataPartition(dataPartition); if (dataPartition.getDataPartitionMap().size() > 1) { throw new IllegalStateException( @@ -132,7 +118,7 @@ public class IndexScan implements RelationalPlanOptimizer { } if (dataPartition.getDataPartitionMap().isEmpty()) { - context.getAnalysis().setFinishQueryAfterAnalyze(); + analysis.setFinishQueryAfterAnalyze(); } else { Set<TRegionReplicaSet> regionReplicaSet = new HashSet<>(); for (Map.Entry< @@ -153,95 +139,35 @@ public class IndexScan implements RelationalPlanOptimizer { return node; } - } - - private static DataPartition fetchDataPartitionByDevices( - List<DeviceEntry> deviceEntries, - String database, - Filter globalTimeFilter, - IPartitionFetcher partitionFetcher, - MPPQueryContext context) { - Pair<List<TTimePartitionSlot>, Pair<Boolean, Boolean>> res = - getTimePartitionSlotList(globalTimeFilter, context); - - // there is no satisfied time range - if (res.left.isEmpty() && Boolean.FALSE.equals(res.right.left)) { - return new DataPartition( - Collections.emptyMap(), - CONFIG.getSeriesPartitionExecutorClass(), - CONFIG.getSeriesPartitionSlotNum()); - } - - Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap = new HashMap<>(); - for (DeviceEntry deviceEntry : deviceEntries) { - DataPartitionQueryParam queryParam = - new DataPartitionQueryParam( - deviceEntry.getDeviceID(), res.left, res.right.left, res.right.right); - sgNameToQueryParamsMap.computeIfAbsent(database, key -> new ArrayList<>()).add(queryParam); - } - - if (res.right.left || res.right.right) { - return partitionFetcher.getDataPartitionWithUnclosedTimeRange(sgNameToQueryParamsMap); - } else { - return partitionFetcher.getDataPartition(sgNameToQueryParamsMap); - } - } - - private static class RewriterContext { - private Expression predicate; - private Metadata metadata; - private final SessionInfo sessionInfo; - private final Analysis analysis; - private final MPPQueryContext queryContext; - private FilterNode filterNode; - - RewriterContext( - Expression predicate, - Metadata metadata, - SessionInfo sessionInfo, - Analysis analysis, - MPPQueryContext queryContext) { - this.predicate = predicate; - this.metadata = metadata; - this.sessionInfo = sessionInfo; - this.analysis = analysis; - this.queryContext = queryContext; - } - - public Expression getPredicate() { - return this.predicate; - } - public void setPredicate(Expression predicate) { - this.predicate = predicate; - } + private DataPartition fetchDataPartitionByDevices( + List<DeviceEntry> deviceEntries, String database, Filter globalTimeFilter) { + Pair<List<TTimePartitionSlot>, Pair<Boolean, Boolean>> res = + getTimePartitionSlotList(globalTimeFilter, queryContext); - public Metadata getMetadata() { - return this.metadata; - } - - public void setMetadata(Metadata metadata) { - this.metadata = metadata; - } - - public SessionInfo getSessionInfo() { - return this.sessionInfo; - } - - public Analysis getAnalysis() { - return this.analysis; - } - - public MPPQueryContext getQueryContext() { - return queryContext; - } + // there is no satisfied time range + if (res.left.isEmpty() && Boolean.FALSE.equals(res.right.left)) { + return new DataPartition( + Collections.emptyMap(), + CONFIG.getSeriesPartitionExecutorClass(), + CONFIG.getSeriesPartitionSlotNum()); + } - public FilterNode getFilterNode() { - return filterNode; - } + List<DataPartitionQueryParam> dataPartitionQueryParams = + deviceEntries.stream() + .map( + deviceEntry -> + new DataPartitionQueryParam( + deviceEntry.getDeviceID(), res.left, res.right.left, res.right.right)) + .collect(Collectors.toList()); + Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap = + Collections.singletonMap(database, dataPartitionQueryParams); - public void setFilterNode(FilterNode filterNode) { - this.filterNode = filterNode; + if (res.right.left || res.right.right) { + return metadata.getDataPartitionWithUnclosedTimeRange(sgNameToQueryParamsMap); + } else { + return metadata.getDataPartition(sgNameToQueryParamsMap); + } } } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/QualifiedName.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/QualifiedName.java index db004cf891b..6b687145b96 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/QualifiedName.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/QualifiedName.java @@ -114,7 +114,7 @@ public class QualifiedName { } /** - * For an identifier of the form "a.b.c.d", returns "a.b.c" For an identifier of the form "a", + * For an identifier of the form "a.b.c.d", returns "a.b.c", For an identifier of the form "a", * returns absent */ public Optional<QualifiedName> getPrefix() { diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/AnalyzerTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/AnalyzerTest.java index 706bba2d0d5..73d89d62177 100644 --- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/AnalyzerTest.java +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/AnalyzerTest.java @@ -165,7 +165,7 @@ public class AnalyzerTest { @Test public void singleTableNoFilterTest() { // wildcard - sql = "SELECT * FROM table1"; + sql = "SELECT * FROM testdb.table1"; actualAnalysis = analyzeSQL(sql, metadata); assertNotNull(actualAnalysis); assertEquals(1, actualAnalysis.getTables().size()); @@ -177,7 +177,7 @@ public class AnalyzerTest { assertTrue(rootNode instanceof OutputNode); assertTrue(((OutputNode) rootNode).getChild() instanceof TableScanNode); tableScanNode = (TableScanNode) ((OutputNode) rootNode).getChild(); - assertEquals("table1", tableScanNode.getQualifiedTableName()); + assertEquals("testdb.table1", tableScanNode.getQualifiedObjectName().toString()); assertEquals( Arrays.asList("time", "tag1", "tag2", "tag3", "attr1", "attr2", "s1", "s2", "s3"), tableScanNode.getOutputColumnNames()); @@ -206,7 +206,7 @@ public class AnalyzerTest { assertTrue(rootNode instanceof OutputNode); assertTrue(((OutputNode) rootNode).getChild() instanceof TableScanNode); tableScanNode = (TableScanNode) ((OutputNode) rootNode).getChild(); - assertEquals("table1", tableScanNode.getQualifiedTableName()); + assertEquals("testdb.table1", tableScanNode.getQualifiedObjectName().toString()); assertEquals( Arrays.asList("time", "tag1", "tag2", "tag3", "attr1", "attr2", "s1", "s2", "s3"), tableScanNode.getOutputColumnNames()); diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestMatadata.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestMatadata.java index f0425d91dc7..b9687cc20c3 100644 --- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestMatadata.java +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestMatadata.java @@ -47,6 +47,7 @@ import org.apache.tsfile.read.common.type.BinaryType; import org.apache.tsfile.read.common.type.Type; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Map; @@ -184,17 +185,12 @@ public class TestMatadata implements Metadata { return true; } - @Override - public IPartitionFetcher getPartitionFetcher() { - return getFakePartitionFetcher(); - } - @Override public List<DeviceEntry> indexScan( QualifiedObjectName tableName, List<Expression> expressionList, List<String> attributeColumns) { - return Arrays.asList( + return Collections.singletonList( new DeviceEntry( new StringArrayDeviceID("root.testdb", "table1", "t1", "t2", "t3"), Arrays.asList("a1", "a2"))); @@ -228,6 +224,18 @@ public class TestMatadata implements Metadata { return null; } + @Override + public DataPartition getDataPartition( + Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap) { + return DATA_PARTITION; + } + + @Override + public DataPartition getDataPartitionWithUnclosedTimeRange( + Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap) { + return DATA_PARTITION; + } + public static boolean isTwoNumericType(List<? extends Type> argumentTypes) { return argumentTypes.size() == 2 && isNumericType(argumentTypes.get(0))
