This is an automated email from the ASF dual-hosted git repository.

jackietien pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 0f6e0d6c7a2 PruneColumn firstly in RelationPlanner
0f6e0d6c7a2 is described below

commit 0f6e0d6c7a2f0973fa2ed7e3c726bd5cda09e900
Author: Jackie Tien <[email protected]>
AuthorDate: Wed Sep 4 11:47:31 2024 +0800

    PruneColumn firstly in RelationPlanner
---
 .../plan/relational/analyzer/Analysis.java         | 14 ++++
 .../relational/analyzer/StatementAnalyzer.java     | 23 ++++--
 .../plan/relational/planner/RelationPlanner.java   | 29 ++++---
 .../plan/relational/planner/TranslationMap.java    | 17 +++--
 .../optimizations/LogicalOptimizeFactory.java      | 89 ++++++++++++++++++++--
 .../plan/relational/security/Identity.java         | 19 +++++
 .../plan/relational/analyzer/AnalyzerTest.java     | 21 ++---
 7 files changed, 171 insertions(+), 41 deletions(-)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analysis.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analysis.java
index 87e7fe15548..4fca93c199e 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analysis.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analysis.java
@@ -70,6 +70,7 @@ import javax.annotation.Nullable;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
@@ -479,6 +480,9 @@ public class Analysis implements IAnalysis {
   }
 
   private <T extends Node> List<T> dereference(Collection<NodeRef<T>> 
nodeRefs) {
+    if (nodeRefs.isEmpty()) {
+      return Collections.emptyList();
+    }
     return nodeRefs.stream().map(NodeRef::getNode).collect(toImmutableList());
   }
 
@@ -517,6 +521,16 @@ public class Analysis implements IAnalysis {
     return columnReferences.containsKey(NodeRef.of(expression));
   }
 
+  public Set<String> getUsedColumns(QualifiedObjectName tableName) {
+    for (Map<QualifiedObjectName, Set<String>> map : 
tableColumnReferences.values()) {
+      Set<String> fields = map.get(tableName);
+      if (fields != null) {
+        return fields;
+      }
+    }
+    return Collections.emptySet();
+  }
+
   public void addTableColumnReferences(
       AccessControl accessControl,
       Identity identity,
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
index a2b91ac794d..df2ee265edf 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
@@ -1381,10 +1381,18 @@ public class StatementAnalyzer {
           }
 
           if (name != null) {
-            List<Field> matchingFields = 
sourceScope.getRelationType().resolveFields(name);
-            if (!matchingFields.isEmpty()) {
-              originTable = matchingFields.get(0).getOriginTable();
-              originColumn = matchingFields.get(0).getOriginColumnName();
+            Field matchingField = null;
+            try {
+              matchingField = analysis.getResolvedField(expression).getField();
+            } catch (IllegalArgumentException e) {
+              List<Field> matchingFields = 
sourceScope.getRelationType().resolveFields(name);
+              if (!matchingFields.isEmpty()) {
+                matchingField = matchingFields.get(0);
+              }
+            }
+            if (matchingField != null) {
+              originTable = matchingField.getOriginTable();
+              originColumn = matchingField.getOriginColumnName();
             }
           }
 
@@ -1582,15 +1590,14 @@ public class StatementAnalyzer {
 
       List<Field> outputFields = fields.build();
 
+      RelationType relationType = new RelationType(outputFields);
       Scope accessControlScope =
-          Scope.builder()
-              .withRelationType(RelationId.anonymous(), new 
RelationType(outputFields))
-              .build();
+          Scope.builder().withRelationType(RelationId.anonymous(), 
relationType).build();
       //      analyzeFiltersAndMasks(table, name, new 
RelationType(outputFields),
       // accessControlScope);
       analysis.registerTable(table, tableSchema, name);
 
-      Scope tableScope = createAndAssignScope(table, scope, outputFields);
+      Scope tableScope = createAndAssignScope(table, scope, relationType);
 
       //      if (addRowIdColumn) {
       //        FieldReference reference = new 
FieldReference(outputFields.size() - 1);
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 cdfb2023ae9..d04e1bd7533 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
@@ -60,6 +60,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
 
 import static java.util.Objects.requireNonNull;
 
@@ -128,14 +129,32 @@ public class RelationPlanner extends 
AstVisitor<RelationPlan, Void> {
     ImmutableList.Builder<Symbol> outputSymbolsBuilder = 
ImmutableList.builder();
     ImmutableMap.Builder<Symbol, ColumnSchema> symbolToColumnSchema = 
ImmutableMap.builder();
     Collection<Field> fields = scope.getRelationType().getAllFields();
+    QualifiedName qualifiedName = analysis.getRelationName(table);
+    if (!qualifiedName.getPrefix().isPresent()) {
+      throw new IllegalStateException("Table " + table.getName() + " has no 
prefix!");
+    }
+
+    QualifiedObjectName qualifiedObjectName =
+        new QualifiedObjectName(
+            
qualifiedName.getPrefix().map(QualifiedName::toString).orElse(null),
+            qualifiedName.getSuffix());
+
+    Set<String> usedColumns = analysis.getUsedColumns(qualifiedObjectName);
+
     // on the basis of that the order of fields is same with the column 
category order of segments
     // in DeviceEntry
     Map<Symbol, Integer> idAndAttributeIndexMap = new HashMap<>();
     int idIndex = 0;
     for (Field field : fields) {
+      TsTableColumnCategory category = field.getColumnCategory();
+      // only keep used columns and all ID columns
+      if (category != TsTableColumnCategory.ID
+          && field.getOriginColumnName().isPresent()
+          && !usedColumns.contains(field.getOriginColumnName().get())) {
+        continue;
+      }
       Symbol symbol = symbolAllocator.newSymbol(field);
       outputSymbolsBuilder.add(symbol);
-      TsTableColumnCategory category = field.getColumnCategory();
       symbolToColumnSchema.put(
           symbol,
           new ColumnSchema(
@@ -146,15 +165,7 @@ public class RelationPlanner extends 
AstVisitor<RelationPlan, Void> {
     }
 
     List<Symbol> outputSymbols = outputSymbolsBuilder.build();
-    QualifiedName qualifiedName = analysis.getRelationName(table);
-    if (!qualifiedName.getPrefix().isPresent()) {
-      throw new IllegalStateException("Table " + table.getName() + " has no 
prefix!");
-    }
 
-    QualifiedObjectName qualifiedObjectName =
-        new QualifiedObjectName(
-            
qualifiedName.getPrefix().map(QualifiedName::toString).orElse(null),
-            qualifiedName.getSuffix());
     Map<Symbol, ColumnSchema> tableColumnSchema = symbolToColumnSchema.build();
     analysis.addTableSchema(qualifiedObjectName, tableColumnSchema);
     TableScanNode tableScanNode =
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TranslationMap.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TranslationMap.java
index 0e2af0b70fe..715111907f6 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TranslationMap.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TranslationMap.java
@@ -43,7 +43,6 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
-import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.base.Verify.verify;
 import static java.lang.String.format;
@@ -131,11 +130,11 @@ public class TranslationMap {
     requireNonNull(astToSymbols, "astToSymbols is null");
     this.astToSymbols = ImmutableMap.copyOf(astToSymbols);
 
-    checkArgument(
-        scope.getLocalScopeFieldCount() == fieldSymbols.length,
-        "scope: %s, fields mappings: %s",
-        scope.getRelationType().getAllFieldCount(),
-        fieldSymbols.length);
+    //    checkArgument(
+    //        scope.getLocalScopeFieldCount() == fieldSymbols.length,
+    //        "scope: %s, fields mappings: %s",
+    //        scope.getRelationType().getAllFieldCount(),
+    //        fieldSymbols.length);
 
     astToSymbols.keySet().stream()
         .map(ScopeAware::getNode)
@@ -383,7 +382,11 @@ public class TranslationMap {
     ResolvedField field = 
analysis.getColumnReferenceFields().get(NodeRef.of(expression));
 
     if (scope.isLocalScope(field.getScope())) {
-      return Optional.of(fieldSymbols[field.getHierarchyFieldIndex()]);
+      if (field.getField().getOriginColumnName().isPresent()) {
+        return 
Optional.of(Symbol.of(field.getField().getOriginColumnName().get()));
+      } else {
+        return Optional.of(fieldSymbols[field.getHierarchyFieldIndex()]);
+      }
     }
 
     if (outerContext.isPresent()) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/LogicalOptimizeFactory.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/LogicalOptimizeFactory.java
index 8acede85ba5..415fa40d6a6 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/LogicalOptimizeFactory.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/LogicalOptimizeFactory.java
@@ -53,6 +53,7 @@ public class LogicalOptimizeFactory {
   public LogicalOptimizeFactory(PlannerContext plannerContext) {
     IrTypeAnalyzer typeAnalyzer = new IrTypeAnalyzer(plannerContext);
     Metadata metadata = plannerContext.getMetadata();
+    RuleStatsRecorder ruleStats = new RuleStatsRecorder();
 
     PlanOptimizer pushPredicateIntoTableScanOptimizer = new 
PushPredicateIntoTableScan();
     PlanOptimizer transformSortToStreamSortOptimizer = new 
TransformSortToStreamSort();
@@ -68,12 +69,31 @@ public class LogicalOptimizeFactory {
             new PruneTableScanColumns(plannerContext.getMetadata()),
             new PruneTopKColumns());
     IterativeOptimizer columnPruningOptimizer =
-        new IterativeOptimizer(plannerContext, new RuleStatsRecorder(), 
columnPruningRules);
+        new IterativeOptimizer(plannerContext, ruleStats, columnPruningRules);
+
+    //    Set<Rule<?>> projectionPushdownRules = ImmutableSet.of(
+    //        new PushProjectionThroughUnion(),
+    //        new PushProjectionThroughExchange(),
+    //        // Dereference pushdown rules
+    //        new PushDownDereferencesThroughMarkDistinct(typeAnalyzer),
+    //        new PushDownDereferenceThroughProject(typeAnalyzer),
+    //        new PushDownDereferenceThroughUnnest(typeAnalyzer),
+    //        new PushDownDereferenceThroughSemiJoin(typeAnalyzer),
+    //        new PushDownDereferenceThroughJoin(typeAnalyzer),
+    //        new PushDownDereferenceThroughFilter(typeAnalyzer),
+    //        new ExtractDereferencesFromFilterAboveScan(typeAnalyzer),
+    //        new PushDownDereferencesThroughLimit(typeAnalyzer),
+    //        new PushDownDereferencesThroughSort(typeAnalyzer),
+    //        new PushDownDereferencesThroughAssignUniqueId(typeAnalyzer),
+    //        new PushDownDereferencesThroughWindow(typeAnalyzer),
+    //        new PushDownDereferencesThroughTopN(typeAnalyzer),
+    //        new PushDownDereferencesThroughRowNumber(typeAnalyzer),
+    //        new PushDownDereferencesThroughTopNRanking(typeAnalyzer));
 
     IterativeOptimizer inlineProjectionLimitFiltersOptimizer =
         new IterativeOptimizer(
             plannerContext,
-            new RuleStatsRecorder(),
+            ruleStats,
             ImmutableSet.of(
                 new InlineProjections(plannerContext),
                 new RemoveRedundantIdentityProjections(),
@@ -88,24 +108,77 @@ public class LogicalOptimizeFactory {
             .add(new RemoveTrivialFilters())
             .build();
     IterativeOptimizer simplifyOptimizer =
-        new IterativeOptimizer(plannerContext, new RuleStatsRecorder(), 
simplifyOptimizerRules);
+        new IterativeOptimizer(plannerContext, ruleStats, 
simplifyOptimizerRules);
 
+    Set<Rule<?>> limitPushdownRules =
+        ImmutableSet.of(new PushLimitThroughOffset(), new 
PushLimitThroughProject());
     IterativeOptimizer limitPushdownOptimizer =
-        new IterativeOptimizer(
-            plannerContext,
-            new RuleStatsRecorder(),
-            ImmutableSet.of(new PushLimitThroughOffset(), new 
PushLimitThroughProject()));
+        new IterativeOptimizer(plannerContext, ruleStats, limitPushdownRules);
 
     PlanOptimizer pushLimitOffsetIntoTableScanOptimizer = new 
PushLimitOffsetIntoTableScan();
 
     IterativeOptimizer topKOptimizer =
         new IterativeOptimizer(
             plannerContext,
-            new RuleStatsRecorder(),
+            ruleStats,
             ImmutableSet.of(new MergeLimitWithSort(), new 
MergeLimitOverProjectWithSort()));
 
     this.planOptimizers =
         ImmutableList.of(
+            new IterativeOptimizer(
+                plannerContext,
+                ruleStats,
+                ImmutableSet.<Rule<?>>builder()
+                    .addAll(columnPruningRules)
+                    //                    .addAll(projectionPushdownRules)
+                    //                    .addAll(new 
UnwrapRowSubscript().rules())
+                    //                    .addAll(new 
PushCastIntoRow().rules())
+                    .addAll(
+                        ImmutableSet.of(
+                            new MergeFilters(),
+                            new InlineProjections(plannerContext),
+                            new RemoveRedundantIdentityProjections(),
+                            new MergeLimits(),
+                            new RemoveTrivialFilters()
+                            //                        new 
RemoveRedundantLimit(),
+                            //                        new 
RemoveRedundantOffset(),
+                            //                        new 
RemoveRedundantSort(),
+                            //                        new 
RemoveRedundantSortBelowLimitWithTies(),
+                            //                        new 
RemoveRedundantTopN(),
+                            //                        new 
RemoveRedundantDistinctLimit(),
+                            //                        new 
ReplaceRedundantJoinWithSource(),
+                            //                        new 
RemoveRedundantJoin(),
+                            //                        new 
ReplaceRedundantJoinWithProject(),
+                            //                        new 
RemoveRedundantExists(),
+                            //                        new 
RemoveRedundantWindow(),
+                            //                        new 
SingleDistinctAggregationToGroupBy(),
+                            //                        new 
MergeLimitWithDistinct(),
+                            //                        new 
PruneCountAggregationOverScalar(metadata),
+                            //                        new 
SimplifyCountOverConstant(plannerContext),
+                            //                        new
+                            // PreAggregateCaseAggregations(plannerContext, 
typeAnalyzer)))
+                            ))
+                    .build()),
+            // MergeUnion and related projection pruning rules must run before 
limit pushdown rules,
+            // otherwise
+            // an intermediate limit node will prevent unions from being 
merged later on
+            new IterativeOptimizer(
+                plannerContext,
+                ruleStats,
+                ImmutableSet.<Rule<?>>builder()
+                    //                    .addAll(projectionPushdownRules)
+                    .addAll(columnPruningRules)
+                    .addAll(limitPushdownRules)
+                    .addAll(
+                        ImmutableSet.of(
+                            //                        new MergeUnion(),
+                            //                        new 
RemoveEmptyUnionBranches(),
+                            new MergeFilters(),
+                            new RemoveTrivialFilters(),
+                            new MergeLimits(),
+                            new InlineProjections(plannerContext),
+                            new RemoveRedundantIdentityProjections()))
+                    .build()),
             simplifyOptimizer,
             columnPruningOptimizer,
             inlineProjectionLimitFiltersOptimizer,
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/Identity.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/Identity.java
index fad9562a916..1f9d13716df 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/Identity.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/Identity.java
@@ -19,6 +19,8 @@
 
 package org.apache.iotdb.db.queryengine.plan.relational.security;
 
+import java.util.Objects;
+
 public class Identity {
   private final String user;
 
@@ -29,4 +31,21 @@ public class Identity {
   public String getUser() {
     return user;
   }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    Identity identity = (Identity) o;
+    return Objects.equals(user, identity.user);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(user);
+  }
 }
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 9024de680b3..ef47e225ba1 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
@@ -939,18 +939,21 @@ public class AnalyzerTest {
     rootNode = logicalQueryPlan.getRootNode();
     distributionPlanner = new TableDistributedPlanner(actualAnalysis, 
logicalQueryPlan, context);
     distributedQueryPlan = distributionPlanner.plan();
+    
assertTrue(actualAnalysis.getRespDatasetHeader().getColumnNameIndexMap().containsKey("time"));
+    
assertTrue(actualAnalysis.getRespDatasetHeader().getColumnNameIndexMap().containsKey("Time"));
+    
assertTrue(actualAnalysis.getRespDatasetHeader().getColumnNameIndexMap().containsKey("_col3"));
+    
assertTrue(actualAnalysis.getRespDatasetHeader().getColumnNameIndexMap().containsKey("_col2"));
+    
assertTrue(actualAnalysis.getRespDatasetHeader().getColumnNameIndexMap().containsKey("tag1"));
+    
assertTrue(actualAnalysis.getRespDatasetHeader().getColumnNameIndexMap().containsKey("TAG1"));
     assertEquals(
-        0, 
actualAnalysis.getRespDatasetHeader().getColumnNameIndexMap().get("Time").intValue());
+        
actualAnalysis.getRespDatasetHeader().getColumnNameIndexMap().get("time").intValue(),
+        
actualAnalysis.getRespDatasetHeader().getColumnNameIndexMap().get("Time").intValue());
     assertEquals(
-        0, 
actualAnalysis.getRespDatasetHeader().getColumnNameIndexMap().get("time").intValue());
+        
actualAnalysis.getRespDatasetHeader().getColumnNameIndexMap().get("_col3").intValue(),
+        
actualAnalysis.getRespDatasetHeader().getColumnNameIndexMap().get("_col2").intValue());
     assertEquals(
-        2, 
actualAnalysis.getRespDatasetHeader().getColumnNameIndexMap().get("_col2").intValue());
-    assertEquals(
-        2, 
actualAnalysis.getRespDatasetHeader().getColumnNameIndexMap().get("_col3").intValue());
-    assertEquals(
-        1, 
actualAnalysis.getRespDatasetHeader().getColumnNameIndexMap().get("tag1").intValue());
-    assertEquals(
-        1, 
actualAnalysis.getRespDatasetHeader().getColumnNameIndexMap().get("TAG1").intValue());
+        
actualAnalysis.getRespDatasetHeader().getColumnNameIndexMap().get("tag1").intValue(),
+        
actualAnalysis.getRespDatasetHeader().getColumnNameIndexMap().get("TAG1").intValue());
   }
 
   private Metadata mockMetadataForInsertion() {

Reply via email to