You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ca...@apache.org on 2024/04/16 01:44:02 UTC
(iotdb) 01/05: add optimizer RemoveRedundantIdentityProjections
This is an automated email from the ASF dual-hosted git repository.
caogaofei pushed a commit to branch ty/TableModelGrammar
in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 34bf1aa11bb08c976c62f4104a888712e61e2076
Author: Beyyes <cg...@foxmail.com>
AuthorDate: Mon Apr 15 20:13:56 2024 +0800
add optimizer RemoveRedundantIdentityProjections
---
.../plan/planner/plan/node/PlanNode.java | 6 +
.../plan/planner/plan/node/PlanVisitor.java | 5 +
.../plan/relational/planner/Assignments.java | 5 +-
.../plan/relational/planner/LogicalPlanner.java | 7 +-
.../plan/relational/planner/PlanBuilder.java | 6 +-
.../plan/relational/planner/QueryPlanner.java | 37 ++--
.../plan/relational/planner/RelationPlan.java | 6 +-
.../plan/relational/planner/RelationPlanner.java | 188 +++++++--------------
.../plan/relational/planner/node/FilterNode.java | 8 +-
.../plan/relational/planner/node/LimitNode.java | 10 +-
.../plan/relational/planner/node/OffsetNode.java | 8 +-
.../plan/relational/planner/node/OutputNode.java | 20 ++-
.../plan/relational/planner/node/ProjectNode.java | 14 +-
.../plan/relational/planner/node/SortNode.java | 12 +-
.../relational/planner/node/TableScanNode.java | 5 +
...ava => RemoveRedundantIdentityProjections.java} | 60 ++++---
.../planner/optimizations/SimplifyExpressions.java | 4 -
.../plan/relational/analyzer/AnalyzerTest.java | 3 +-
18 files changed, 207 insertions(+), 197 deletions(-)
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanNode.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanNode.java
index 877db9bf543..b8a9ebf66f6 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanNode.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanNode.java
@@ -22,6 +22,7 @@ package org.apache.iotdb.db.queryengine.plan.planner.plan.node;
import org.apache.iotdb.commons.exception.runtime.SerializationRunTimeException;
import org.apache.iotdb.consensus.common.request.IConsensusRequest;
import org.apache.iotdb.db.queryengine.plan.analyze.TypeProvider;
+import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol;
import org.apache.iotdb.tsfile.utils.PublicBAOS;
import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
@@ -206,4 +207,9 @@ public abstract class PlanNode implements IConsensusRequest {
public int hashCode() {
return Objects.hash(id);
}
+
+ // =========================== Used for Relational Model ============================
+ public List<Symbol> getOutputSymbols() {
+ throw new UnsupportedOperationException("This planNode does not support getOutputSymbols().");
+ }
}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanVisitor.java
index 9e893bbc653..393f46a43ba 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanVisitor.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanVisitor.java
@@ -518,4 +518,9 @@ public abstract class PlanVisitor<R, C> {
public R visitTableScan(TableScanNode node, C context) {
return visitPlan(node, context);
}
+
+ public R visitProject(
+ org.apache.iotdb.db.queryengine.plan.relational.planner.node.ProjectNode node, C context) {
+ return visitPlan(node, context);
+ }
}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/Assignments.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/Assignments.java
index 992ada2a745..a439f41f00b 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/Assignments.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/Assignments.java
@@ -37,6 +37,9 @@ import static java.util.Arrays.asList;
import static java.util.Objects.requireNonNull;
public class Assignments {
+
+ private final Map<Symbol, Expression> assignments;
+
public static Builder builder() {
return new Builder();
}
@@ -66,8 +69,6 @@ public class Assignments {
return builder().put(symbol1, expression1).put(symbol2, expression2).build();
}
- private final Map<Symbol, Expression> assignments;
-
@JsonCreator
public Assignments(@JsonProperty("assignments") Map<Symbol, Expression> assignments) {
this.assignments = ImmutableMap.copyOf(requireNonNull(assignments, "assignments is null"));
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LogicalPlanner.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LogicalPlanner.java
index f11c0d86f98..5e54848763f 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LogicalPlanner.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LogicalPlanner.java
@@ -25,6 +25,7 @@ import org.apache.iotdb.db.queryengine.plan.relational.analyzer.RelationType;
import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.OutputNode;
import org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations.RelationalPlanOptimizer;
+import org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations.RemoveRedundantIdentityProjections;
import org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations.SimplifyExpressions;
import org.apache.iotdb.db.relational.sql.tree.Query;
import org.apache.iotdb.db.relational.sql.tree.Statement;
@@ -34,7 +35,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import io.airlift.log.Logger;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import static java.util.Objects.requireNonNull;
@@ -58,8 +59,8 @@ public class LogicalPlanner {
this.sessionInfo = requireNonNull(sessionInfo, "session is null");
this.warningCollector = requireNonNull(warningCollector, "warningCollector is null");
- this.relationalPlanOptimizers = new ArrayList<>();
- this.relationalPlanOptimizers.add(new SimplifyExpressions());
+ this.relationalPlanOptimizers =
+ Arrays.asList(new SimplifyExpressions(), new RemoveRedundantIdentityProjections());
}
public LogicalQueryPlan plan(Analysis analysis) throws IoTDBException {
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlanBuilder.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlanBuilder.java
index 2045233cb37..a34e17dbf85 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlanBuilder.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlanBuilder.java
@@ -29,7 +29,8 @@ import java.util.Map;
import static java.util.Objects.requireNonNull;
-class PlanBuilder {
+public class PlanBuilder {
+
private final PlanNode root;
public PlanBuilder(PlanNode root) {
@@ -68,8 +69,7 @@ class PlanBuilder {
Assignments.Builder projections = Assignments.builder();
// add an identity projection for underlying plan
- // TODO needed?
- // projections.putIdentities(root.getOutputSymbols());
+ projections.putIdentities(root.getOutputSymbols());
Map<ScopeAware<Expression>, Symbol> mappings = new HashMap<>();
// for (T expression : expressions) {
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/QueryPlanner.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/QueryPlanner.java
index eb23a4a2cbf..768cd3ca4b5 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/QueryPlanner.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/QueryPlanner.java
@@ -28,6 +28,7 @@ import org.apache.iotdb.db.relational.sql.tree.Node;
import org.apache.iotdb.db.relational.sql.tree.Offset;
import org.apache.iotdb.db.relational.sql.tree.OrderBy;
import org.apache.iotdb.db.relational.sql.tree.Query;
+import org.apache.iotdb.db.relational.sql.tree.QueryBody;
import org.apache.iotdb.db.relational.sql.tree.QuerySpecification;
import org.apache.iotdb.db.relational.sql.tree.SortItem;
import org.apache.iotdb.tsfile.read.common.type.Type;
@@ -47,18 +48,17 @@ import static java.util.Objects.requireNonNull;
import static org.apache.iotdb.db.queryengine.plan.relational.planner.OrderingTranslator.sortItemToSortOrder;
import static org.apache.iotdb.db.queryengine.plan.relational.planner.PlanBuilder.newPlanBuilder;
-class QueryPlanner {
- private static final int MAX_BIGINT_PRECISION = 19;
+public class QueryPlanner {
private final Analysis analysis;
private final SymbolAllocator symbolAllocator;
private final QueryId idAllocator;
- // private final Map<NodeRef<LambdaArgumentDeclaration>, Symbol> lambdaDeclarationToSymbolMap;
- // private final PlannerContext plannerContext;
private final SessionInfo session;
- // private final SubqueryPlanner subqueryPlanner;
private final Map<NodeRef<Node>, RelationPlan> recursiveSubqueries;
- QueryPlanner(
+ // private final Map<NodeRef<LambdaArgumentDeclaration>, Symbol> lambdaDeclarationToSymbolMap;
+ // private final SubqueryPlanner subqueryPlanner;
+
+ public QueryPlanner(
Analysis analysis,
SymbolAllocator symbolAllocator,
QueryId idAllocator,
@@ -74,12 +74,11 @@ class QueryPlanner {
this.symbolAllocator = symbolAllocator;
this.idAllocator = idAllocator;
this.session = session;
- // this.subqueryPlanner = null;
this.recursiveSubqueries = recursiveSubqueries;
}
public RelationPlan plan(Query query) {
- PlanBuilder builder = planQueryBody(query);
+ PlanBuilder builder = planQueryBody(query.getQueryBody());
List<Expression> orderBy = analysis.getOrderByExpressions(query);
// builder = subqueryPlanner.handleSubqueries(builder, orderBy, analysis.getSubqueries(query));
@@ -108,20 +107,16 @@ class QueryPlanner {
PlanBuilder builder = planFrom(node);
builder = filter(builder, analysis.getWhere(node), node);
- // builder = aggregate(builder, node);
- builder = filter(builder, analysis.getHaving(node), node);
- // builder = planWindowFunctions(node, builder,
- // ImmutableList.copyOf(analysis.getWindowFunctions(node)));
- // builder = planWindowMeasures(node, builder,
- // ImmutableList.copyOf(analysis.getWindowMeasures(node)));
+
+ // TODO prcess aggregate, having later
List<Analysis.SelectExpression> selectExpressions = analysis.getSelectExpressions(node);
List<Expression> expressions =
selectExpressions.stream()
.map(Analysis.SelectExpression::getExpression)
.collect(toImmutableList());
- // builder = subqueryPlanner.handleSubqueries(builder, expressions,
- // analysis.getSubqueries(node));
+
+ // TODO process subQuery later
if (hasExpressionsToUnfold(selectExpressions)) {
// pre-project the folded expressions to preserve any non-deterministic semantics of functions
@@ -160,10 +155,12 @@ class QueryPlanner {
}
List<Expression> orderBy = analysis.getOrderByExpressions(node);
+ // TODO this appendProjections may be removed
builder =
builder.appendProjections(Iterables.concat(orderBy, outputs), symbolAllocator, idAllocator);
- // builder = distinct(builder, node, outputs);
+ // TODO handle distinct
+
Optional<OrderingScheme> orderingScheme =
orderingScheme(builder, node.getOrderBy(), analysis.getOrderByExpressions(node));
builder = sort(builder, orderingScheme);
@@ -208,10 +205,10 @@ class QueryPlanner {
return outputSymbols.build();
}
- private PlanBuilder planQueryBody(Query query) {
+ private PlanBuilder planQueryBody(QueryBody queryBody) {
RelationPlan relationPlan =
new RelationPlanner(analysis, symbolAllocator, idAllocator, session, recursiveSubqueries)
- .process(query.getQueryBody(), null);
+ .process(queryBody, null);
return newPlanBuilder(relationPlan, analysis, session);
}
@@ -223,7 +220,7 @@ class QueryPlanner {
.process(node.getFrom().get(), null);
return newPlanBuilder(relationPlan, analysis, session);
} else {
- throw new RuntimeException("From clause must not by empty");
+ throw new IllegalStateException("From clause must not by empty");
}
}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/RelationPlan.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/RelationPlan.java
index 5ece186d194..cdd1bab217f 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/RelationPlan.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/RelationPlan.java
@@ -29,15 +29,15 @@ import static java.util.Objects.requireNonNull;
* values, etc.), and the mapping to indicate how the fields (by position) in the relation map to
* the outputs of the plan.
*/
-class RelationPlan {
+public class RelationPlan {
private final PlanNode root;
+ private final Scope scope;
+
// for each field in the relation, the corresponding symbol from "root"
private final List<Symbol> fieldMappings;
- private final Scope scope;
-
public RelationPlan(PlanNode root, Scope scope, List<Symbol> fieldMappings) {
requireNonNull(root, "root is null");
requireNonNull(fieldMappings, "fieldMappings is null");
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 9e180d3dc4c..b42cc50c693 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
@@ -25,11 +25,17 @@ import org.apache.iotdb.db.queryengine.plan.relational.metadata.TableHandle;
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.TableScanNode;
import org.apache.iotdb.db.relational.sql.tree.AliasedRelation;
import org.apache.iotdb.db.relational.sql.tree.AstVisitor;
+import org.apache.iotdb.db.relational.sql.tree.Except;
+import org.apache.iotdb.db.relational.sql.tree.Intersect;
+import org.apache.iotdb.db.relational.sql.tree.Join;
import org.apache.iotdb.db.relational.sql.tree.Node;
import org.apache.iotdb.db.relational.sql.tree.Query;
import org.apache.iotdb.db.relational.sql.tree.QuerySpecification;
import org.apache.iotdb.db.relational.sql.tree.SubqueryExpression;
import org.apache.iotdb.db.relational.sql.tree.Table;
+import org.apache.iotdb.db.relational.sql.tree.TableSubquery;
+import org.apache.iotdb.db.relational.sql.tree.Union;
+import org.apache.iotdb.db.relational.sql.tree.Values;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -40,14 +46,14 @@ import java.util.Map;
import static java.util.Objects.requireNonNull;
-class RelationPlanner extends AstVisitor<RelationPlan, Void> {
+public class RelationPlanner extends AstVisitor<RelationPlan, Void> {
private final Analysis analysis;
private final SymbolAllocator symbolAllocator;
private final QueryId idAllocator;
private final SessionInfo session;
private final Map<NodeRef<Node>, RelationPlan> recursiveSubqueries;
- RelationPlanner(
+ public RelationPlanner(
Analysis analysis,
SymbolAllocator symbolAllocator,
QueryId idAllocator,
@@ -67,8 +73,9 @@ class RelationPlanner extends AstVisitor<RelationPlan, Void> {
}
@Override
- protected RelationPlan visitNode(Node node, Void context) {
- throw new IllegalStateException("Unsupported node type: " + node.getClass().getName());
+ protected RelationPlan visitQuery(Query node, Void context) {
+ return new QueryPlanner(analysis, symbolAllocator, idAllocator, session, recursiveSubqueries)
+ .plan(node);
}
@Override
@@ -83,154 +90,81 @@ class RelationPlanner extends AstVisitor<RelationPlan, Void> {
expansion.getRoot(), expansion.getScope(), expansion.getFieldMappings());
}
- Query namedQuery = analysis.getNamedQuery(node);
Scope scope = analysis.getScope(node);
+ TableHandle tableHandle = analysis.getTableHandle(node);
- RelationPlan plan;
- if (namedQuery != null) {
- throw new RuntimeException("NamedQuery is not supported");
- } else {
- TableHandle handle = analysis.getTableHandle(node);
+ ImmutableList.Builder<Symbol> outputSymbolsBuilder = ImmutableList.builder();
+ ImmutableMap.Builder<Symbol, ColumnHandle> columnsBuilder = ImmutableMap.builder();
- ImmutableList.Builder<Symbol> outputSymbolsBuilder = ImmutableList.builder();
- ImmutableMap.Builder<Symbol, ColumnHandle> columns = ImmutableMap.builder();
-
- // Collection<Field> fields = analysis.getMaterializedViewStorageTableFields(node);
- Collection<Field> fields = scope.getRelationType().getAllFields();
- for (Field field : fields) {
- Symbol symbol = symbolAllocator.newSymbol(field);
+ Collection<Field> fields = scope.getRelationType().getAllFields();
+ for (Field field : fields) {
+ Symbol symbol = symbolAllocator.newSymbol(field);
+ outputSymbolsBuilder.add(symbol);
+ columnsBuilder.put(symbol, analysis.getColumn(field));
+ }
- outputSymbolsBuilder.add(symbol);
- columns.put(symbol, analysis.getColumn(field));
- }
+ List<Symbol> outputSymbols = outputSymbolsBuilder.build();
+ PlanNode root =
+ new TableScanNode(
+ idAllocator.genPlanNodeId(), tableHandle, outputSymbols, columnsBuilder.buildOrThrow());
- List<Symbol> outputSymbols = outputSymbolsBuilder.build();
- PlanNode root =
- new TableScanNode(
- idAllocator.genPlanNodeId(), handle, outputSymbols, columns.buildOrThrow());
+ return new RelationPlan(root, scope, outputSymbols);
- plan = new RelationPlan(root, scope, outputSymbols);
- }
-
- // TODO what's the meaning of RowFilters addColumnMasks?
+ // Query namedQuery = analysis.getNamedQuery(node);
+ // Collection<Field> fields = analysis.getMaterializedViewStorageTableFields(node);
// plan = addRowFilters(node, plan);
// plan = addColumnMasks(node, plan);
-
- return plan;
}
- // private RelationPlan addRowFilters(Table node, RelationPlan plan) {
- // return addRowFilters(node, plan, Function.identity());
- // }
-
- // public RelationPlan addRowFilters(
- // Table node, RelationPlan plan, Function<Expression, Expression> predicateTransformation) {
- // List<Expression> filters = null;
- // // analysis.getRowFilters(node);
- //
- // if (filters.isEmpty()) {
- // return plan;
- // }
- //
- // // The fields in the access control scope has the same layout as those for the table scope
- // PlanBuilder planBuilder = newPlanBuilder(plan, analysis, session);
- // // .withScope(accessControlScope.apply(node), plan.getFieldMappings());
- //
- // for (Expression filter : filters) {
- // // planBuilder = subqueryPlanner.handleSubqueries(planBuilder, filter,
- // // analysis.getSubqueries(filter));
- //
- // Expression predicate = coerceIfNecessary(analysis, filter, filter);
- // predicate = predicateTransformation.apply(predicate);
- // planBuilder =
- // planBuilder.withNewRoot(
- // new FilterNode(idAllocator.genPlanNodeId(), planBuilder.getRoot(), predicate));
- // }
- //
- // return new RelationPlan(planBuilder.getRoot(), plan.getScope(), plan.getFieldMappings());
- // }
-
- // private RelationPlan addColumnMasks(Table table, RelationPlan plan) {
- // Map<String, Expression> columnMasks = analysis.getColumnMasks(table);
- //
- // // A Table can represent a WITH query, which can have anonymous fields. On the other
- // hand,
- // // it can't have masks. The loop below expects fields to have proper names, so bail out
- // // if the masks are missing
- // if (columnMasks.isEmpty()) {
- // return plan;
- // }
- //
- // // The fields in the access control scope has the same layout as those for the table
- // scope
- // PlanBuilder planBuilder = newPlanBuilder(plan, analysis, session)
- // .withScope(analysis.getAccessControlScope(table), plan.getFieldMappings());
- //
- // Assignments.Builder assignments = Assignments.builder();
- // assignments.putIdentities(planBuilder.getRoot().getOutputSymbols());
- //
- // List<Symbol> fieldMappings = new ArrayList<>();
- // for (int i = 0; i < plan.getDescriptor().getAllFieldCount(); i++) {
- // Field field = plan.getDescriptor().getFieldByIndex(i);
- //
- // Expression mask = columnMasks.get(field.getName().orElseThrow());
- // Symbol symbol = plan.getFieldMappings().get(i);
- // Expression projection = symbol.toSymbolReference();
- // if (mask != null) {
- // symbol = symbolAllocator.newSymbol(symbol);
- // projection = coerceIfNecessary(analysis, mask, planBuilder.rewrite(mask));
- // }
- //
- // assignments.put(symbol, projection);
- // fieldMappings.add(symbol);
- // }
- //
- // planBuilder = planBuilder
- // .withNewRoot(new ProjectNode(
- // idAllocator.genPlanNodeId(),
- // planBuilder.getRoot(),
- // assignments.build()));
- //
- // return new RelationPlan(planBuilder.getRoot(), plan.getScope(), fieldMappings);
- // }
+ @Override
+ protected RelationPlan visitQuerySpecification(QuerySpecification node, Void context) {
+ return new QueryPlanner(analysis, symbolAllocator, idAllocator, session, recursiveSubqueries)
+ .plan(node);
+ }
@Override
- protected RelationPlan visitAliasedRelation(AliasedRelation node, Void context) {
- RelationPlan subPlan = process(node.getRelation(), context);
+ protected RelationPlan visitNode(Node node, Void context) {
+ throw new IllegalStateException("Unsupported node type: " + node.getClass().getName());
+ }
- PlanNode root = subPlan.getRoot();
- List<Symbol> mappings = subPlan.getFieldMappings();
+ // ================================ Implemented later =====================================
+ @Override
+ protected RelationPlan visitTableSubquery(TableSubquery node, Void context) {
+ throw new IllegalStateException("TableSubquery is not supported in current version.");
+ }
- if (node.getColumnNames() != null) {
- ImmutableList.Builder<Symbol> newMappings = ImmutableList.builder();
+ @Override
+ protected RelationPlan visitValues(Values node, Void context) {
+ throw new IllegalStateException("Values is not supported in current version.");
+ }
- // Adjust the mappings to expose only the columns visible in the scope of the aliased relation
- for (int i = 0; i < subPlan.getDescriptor().getAllFieldCount(); i++) {
- if (!subPlan.getDescriptor().getFieldByIndex(i).isHidden()) {
- newMappings.add(subPlan.getFieldMappings().get(i));
- }
- }
+ @Override
+ protected RelationPlan visitSubqueryExpression(SubqueryExpression node, Void context) {
+ throw new IllegalStateException("SubqueryExpression is not supported in current version.");
+ }
- mappings = newMappings.build();
- }
+ @Override
+ protected RelationPlan visitJoin(Join node, Void context) {
+ throw new IllegalStateException("Join is not supported in current version.");
+ }
- return new RelationPlan(root, analysis.getScope(node), mappings);
+ @Override
+ protected RelationPlan visitAliasedRelation(AliasedRelation node, Void context) {
+ throw new IllegalStateException("AliasedRelation is not supported in current version.");
}
@Override
- protected RelationPlan visitQuery(Query node, Void context) {
- return new QueryPlanner(analysis, symbolAllocator, idAllocator, session, recursiveSubqueries)
- .plan(node);
+ protected RelationPlan visitIntersect(Intersect node, Void context) {
+ throw new IllegalStateException("Intersect is not supported in current version.");
}
@Override
- protected RelationPlan visitQuerySpecification(QuerySpecification node, Void context) {
- return new QueryPlanner(analysis, symbolAllocator, idAllocator, session, recursiveSubqueries)
- .plan(node);
+ protected RelationPlan visitUnion(Union node, Void context) {
+ throw new IllegalStateException("Union is not supported in current version.");
}
@Override
- protected RelationPlan visitSubqueryExpression(SubqueryExpression node, Void context) {
- return process(node.getQuery(), context);
+ protected RelationPlan visitExcept(Except node, Void context) {
+ throw new IllegalStateException("Except is not supported in current version.");
}
}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/FilterNode.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/FilterNode.java
index 3c49baa4880..68289d5a83d 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/FilterNode.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/FilterNode.java
@@ -23,6 +23,7 @@ import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNodeId;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanVisitor;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.SingleChildProcessNode;
+import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol;
import org.apache.iotdb.db.relational.sql.tree.Expression;
import java.io.DataOutputStream;
@@ -45,7 +46,7 @@ public class FilterNode extends SingleChildProcessNode {
@Override
public PlanNode clone() {
- return null;
+ return new FilterNode(id, child, predicate);
}
@Override
@@ -66,4 +67,9 @@ public class FilterNode extends SingleChildProcessNode {
public void setPredicate(Expression predicate) {
this.predicate = predicate;
}
+
+ @Override
+ public List<Symbol> getOutputSymbols() {
+ return child.getOutputSymbols();
+ }
}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/LimitNode.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/LimitNode.java
index 41b376e04be..17481074932 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/LimitNode.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/LimitNode.java
@@ -4,6 +4,7 @@ import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNodeId;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.SingleChildProcessNode;
import org.apache.iotdb.db.queryengine.plan.relational.planner.OrderingScheme;
+import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol;
import java.io.DataOutputStream;
import java.io.IOException;
@@ -13,7 +14,7 @@ import java.util.Optional;
public class LimitNode extends SingleChildProcessNode {
private final long count;
- // what's the meaning?
+ // TODO what's the meaning?
private final Optional<OrderingScheme> tiesResolvingScheme;
// private final boolean partial;
// private final List<Symbol> preSortedInputs;
@@ -27,7 +28,7 @@ public class LimitNode extends SingleChildProcessNode {
@Override
public PlanNode clone() {
- return null;
+ return new LimitNode(id, child, count, tiesResolvingScheme);
}
@Override
@@ -40,4 +41,9 @@ public class LimitNode extends SingleChildProcessNode {
@Override
protected void serializeAttributes(DataOutputStream stream) throws IOException {}
+
+ @Override
+ public List<Symbol> getOutputSymbols() {
+ return child.getOutputSymbols();
+ }
}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/OffsetNode.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/OffsetNode.java
index c4ea93a27cb..69ac2517e83 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/OffsetNode.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/OffsetNode.java
@@ -3,6 +3,7 @@ package org.apache.iotdb.db.queryengine.plan.relational.planner.node;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNodeId;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.SingleChildProcessNode;
+import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol;
import java.io.DataOutputStream;
import java.io.IOException;
@@ -19,7 +20,7 @@ public class OffsetNode extends SingleChildProcessNode {
@Override
public PlanNode clone() {
- return null;
+ return new OffsetNode(id, child, count);
}
@Override
@@ -32,4 +33,9 @@ public class OffsetNode extends SingleChildProcessNode {
@Override
protected void serializeAttributes(DataOutputStream stream) throws IOException {}
+
+ @Override
+ public List<Symbol> getOutputSymbols() {
+ return child.getOutputSymbols();
+ }
}
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 cb884b09a56..514a7bce382 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
@@ -5,6 +5,8 @@ import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNodeId;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.SingleChildProcessNode;
import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol;
+import com.google.common.collect.ImmutableList;
+
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -12,22 +14,22 @@ import java.util.List;
public class OutputNode extends SingleChildProcessNode {
- private final List<String> outputColumnNames;
+ private final List<String> columnNames;
- private final List<Symbol> symbols;
+ // column name = symbol
+ private final List<Symbol> outputs;
- public OutputNode(
- PlanNodeId id, PlanNode child, List<String> outputColumnNames, List<Symbol> symbols) {
+ public OutputNode(PlanNodeId id, PlanNode child, List<String> columnNames, List<Symbol> outputs) {
super(id, child);
this.id = id;
this.child = child;
- this.outputColumnNames = outputColumnNames;
- this.symbols = symbols;
+ this.columnNames = ImmutableList.copyOf(columnNames);
+ this.outputs = ImmutableList.copyOf(outputs);
}
@Override
public PlanNode clone() {
- return null;
+ return new OutputNode(id, child, columnNames, outputs);
}
@Override
@@ -40,4 +42,8 @@ public class OutputNode extends SingleChildProcessNode {
@Override
protected void serializeAttributes(DataOutputStream stream) throws IOException {}
+
+ public List<Symbol> getOutputSymbols() {
+ return outputs;
+ }
}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/ProjectNode.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/ProjectNode.java
index ff8de50de27..ed65602cf9e 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/ProjectNode.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/ProjectNode.java
@@ -2,8 +2,10 @@ package org.apache.iotdb.db.queryengine.plan.relational.planner.node;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNodeId;
+import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanVisitor;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.SingleChildProcessNode;
import org.apache.iotdb.db.queryengine.plan.relational.planner.Assignments;
+import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol;
import java.io.DataOutputStream;
import java.io.IOException;
@@ -18,9 +20,14 @@ public class ProjectNode extends SingleChildProcessNode {
this.assignments = assignments;
}
+ @Override
+ public <R, C> R accept(PlanVisitor<R, C> visitor, C context) {
+ return visitor.visitProject(this, context);
+ }
+
@Override
public PlanNode clone() {
- return null;
+ return new ProjectNode(id, child, assignments);
}
@Override
@@ -33,4 +40,9 @@ public class ProjectNode extends SingleChildProcessNode {
@Override
protected void serializeAttributes(DataOutputStream stream) throws IOException {}
+
+ @Override
+ public List<Symbol> getOutputSymbols() {
+ return assignments.getOutputs();
+ }
}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/SortNode.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/SortNode.java
index 37358d3d696..2ea9f7081c2 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/SortNode.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/node/SortNode.java
@@ -4,6 +4,7 @@ import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNodeId;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.SingleChildProcessNode;
import org.apache.iotdb.db.queryengine.plan.relational.planner.OrderingScheme;
+import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol;
import java.io.DataOutputStream;
import java.io.IOException;
@@ -14,15 +15,15 @@ public class SortNode extends SingleChildProcessNode {
private final OrderingScheme orderingScheme;
private final boolean partial;
- public SortNode(PlanNodeId id, PlanNode planNode, OrderingScheme scheme, boolean partial) {
- super(id, planNode);
+ public SortNode(PlanNodeId id, PlanNode child, OrderingScheme scheme, boolean partial) {
+ super(id, child);
this.orderingScheme = scheme;
this.partial = partial;
}
@Override
public PlanNode clone() {
- return null;
+ return new SortNode(id, child, orderingScheme, partial);
}
@Override
@@ -35,4 +36,9 @@ public class SortNode extends SingleChildProcessNode {
@Override
protected void serializeAttributes(DataOutputStream stream) throws IOException {}
+
+ @Override
+ public List<Symbol> getOutputSymbols() {
+ return child.getOutputSymbols();
+ }
}
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 1b7c2476ba3..68eb557a38b 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
@@ -62,4 +62,9 @@ public class TableScanNode extends PlanNode {
@Override
protected void serializeAttributes(DataOutputStream stream) throws IOException {}
+
+ @Override
+ public List<Symbol> getOutputSymbols() {
+ return outputSymbols;
+ }
}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/SimplifyExpressions.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/RemoveRedundantIdentityProjections.java
similarity index 52%
copy from iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/SimplifyExpressions.java
copy to iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/RemoveRedundantIdentityProjections.java
index aef419fa123..d7366dfe9df 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/SimplifyExpressions.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/RemoveRedundantIdentityProjections.java
@@ -17,42 +17,52 @@ package org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations;
import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
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.planner.plan.node.process.SingleChildProcessNode;
import org.apache.iotdb.db.queryengine.plan.relational.analyzer.Analysis;
-import org.apache.iotdb.db.queryengine.plan.relational.planner.node.FilterNode;
+import org.apache.iotdb.db.queryengine.plan.relational.planner.node.ProjectNode;
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.TableScanNode;
-import org.apache.iotdb.db.relational.sql.tree.Expression;
-import static org.apache.iotdb.db.queryengine.plan.relational.planner.ir.ExtractCommonPredicatesExpressionRewriter.extractCommonPredicates;
-import static org.apache.iotdb.db.queryengine.plan.relational.planner.ir.NormalizeOrExpressionRewriter.normalizeOrExpression;
+import java.util.Collections;
+import java.util.List;
-public class SimplifyExpressions implements RelationalPlanOptimizer {
+public class RemoveRedundantIdentityProjections implements RelationalPlanOptimizer {
@Override
public PlanNode optimize(PlanNode planNode, Analysis analysis, MPPQueryContext context) {
- // TODO add query statement pruning
return planNode.accept(new Rewriter(), new RewriterContext());
}
private static class Rewriter extends PlanVisitor<PlanNode, RewriterContext> {
-
@Override
public PlanNode visitPlan(PlanNode node, RewriterContext context) {
- // PlanNode newNode = node.clone();
- if (node.getChildren() == null) {
- System.out.println("aa");
- }
+ PlanNode newNode = node.clone();
for (PlanNode child : node.getChildren()) {
- child.accept(this, context);
+ context.setParent(node);
+ newNode.addChild(child.accept(this, context));
}
- return node;
+ return newNode;
}
@Override
- public PlanNode visitFilter(FilterNode node, RewriterContext context) {
- Expression predicate = normalizeOrExpression(node.getPredicate());
- predicate = extractCommonPredicates(predicate);
- node.setPredicate(predicate);
- return node;
+ public PlanNode visitProject(ProjectNode projectNode, RewriterContext context) {
+ if (projectNode.getOutputSymbols().equals(projectNode.getChild().getOutputSymbols())) {
+ if (context.getParent() instanceof SingleChildProcessNode) {
+ ((SingleChildProcessNode) context.getParent()).setChild(projectNode.getChild());
+ } else {
+ List<PlanNode> children = context.getParent().getChildren();
+ for (int i = 0; i < children.size(); i++) {
+ PlanNode child = children.get(i);
+ if (child.getPlanNodeId().equals(projectNode.getPlanNodeId())) {
+ Collections.swap(children, i, children.size() - 1);
+ children.remove(children.size() - 1);
+ break;
+ }
+ }
+ }
+ return projectNode.getChild();
+ } else {
+ return projectNode;
+ }
}
@Override
@@ -61,5 +71,17 @@ public class SimplifyExpressions implements RelationalPlanOptimizer {
}
}
- private static class RewriterContext {}
+ private static class RewriterContext {
+ private PlanNode parent;
+
+ public RewriterContext() {}
+
+ public PlanNode getParent() {
+ return this.parent;
+ }
+
+ public void setParent(PlanNode parent) {
+ this.parent = parent;
+ }
+ }
}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/SimplifyExpressions.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/SimplifyExpressions.java
index aef419fa123..1e5839fe32a 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/SimplifyExpressions.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/SimplifyExpressions.java
@@ -37,10 +37,6 @@ public class SimplifyExpressions implements RelationalPlanOptimizer {
@Override
public PlanNode visitPlan(PlanNode node, RewriterContext context) {
- // PlanNode newNode = node.clone();
- if (node.getChildren() == null) {
- System.out.println("aa");
- }
for (PlanNode child : node.getChildren()) {
child.accept(this, context);
}
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 c42342c16cd..143bd906fbe 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
@@ -134,9 +134,10 @@ public class AnalyzerTest {
@Test
public void testSingleTableQuery() throws IoTDBException {
+ // no sort
String sql =
"SELECT tag1 as tt, tag2, attr1, s1+1 FROM table1 "
- + "WHERE time>1 AND tag1='A' OR s2>3 ORDER BY time DESC OFFSET 10 LIMIT 5";
+ + "WHERE time>1 AND tag1='A' OR s2>3 OFFSET 10 LIMIT 5";
Metadata metadata = new TestMatadata();
Analysis actualAnalysis = analyzeSQL(sql, metadata);