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

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


The following commit(s) were added to refs/heads/SortPrune by this push:
     new 37faccce96f Fix UT
37faccce96f is described below

commit 37faccce96f8023929b9ef2c59129f6318702941
Author: JackieTien97 <[email protected]>
AuthorDate: Tue Nov 19 20:57:16 2024 +0800

    Fix UT
---
 .../plan/planner/TableOperatorGenerator.java       | 35 +++++++++++++++-----
 .../distribute/TableDistributedPlanGenerator.java  |  7 ++--
 .../TableModelTypeProviderExtractor.java           |  5 +++
 .../iterative/rule/PruneTableScanColumns.java      | 12 +++----
 .../relational/planner/node/TableScanNode.java     | 18 +++++++++++
 .../PushAggregationIntoTableScan.java              | 12 ++++---
 .../PushLimitOffsetIntoTableScan.java              |  3 +-
 .../planner/optimizations/SortElimination.java     | 16 ++++++++--
 .../optimizations/TransformSortToStreamSort.java   |  5 ++-
 .../plan/relational/analyzer/JoinTest.java         | 37 ++++++++--------------
 .../plan/relational/analyzer/TestUtils.java        |  6 ++--
 11 files changed, 98 insertions(+), 58 deletions(-)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
index 6fce84dabc9..d55417013b0 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
@@ -1187,19 +1187,38 @@ public class TableOperatorGenerator extends 
PlanVisitor<Operator, LocalExecution
     Operator leftChild = node.getLeftChild().accept(this, context);
     Operator rightChild = node.getRightChild().accept(this, context);
 
-    int leftTimeColumnPosition =
-        
node.getLeftChild().getOutputSymbols().indexOf(node.getCriteria().get(0).getLeft());
+    ImmutableMap<Symbol, Integer> leftColumnNamesMap =
+        makeLayoutFromOutputSymbols(node.getLeftChild().getOutputSymbols());
+    Integer leftTimeColumnPosition = 
leftColumnNamesMap.get(node.getCriteria().get(0).getLeft());
+    if (leftTimeColumnPosition == null) {
+      throw new IllegalStateException("Left child of JoinNode doesn't contain 
time column");
+    }
     int[] leftOutputSymbolIdx = new int[node.getLeftOutputSymbols().size()];
     for (int i = 0; i < leftOutputSymbolIdx.length; i++) {
-      leftOutputSymbolIdx[i] =
-          
node.getLeftChild().getOutputSymbols().indexOf(node.getLeftOutputSymbols().get(i));
+      Integer index = 
leftColumnNamesMap.get(node.getLeftOutputSymbols().get(i));
+      if (index == null) {
+        throw new IllegalStateException(
+            "Left child of JoinNode doesn't contain LeftOutputSymbol "
+                + node.getLeftOutputSymbols().get(i));
+      }
+      leftOutputSymbolIdx[i] = index;
+    }
+
+    ImmutableMap<Symbol, Integer> rightColumnNamesMap =
+        makeLayoutFromOutputSymbols(node.getRightChild().getOutputSymbols());
+    Integer rightTimeColumnPosition = 
rightColumnNamesMap.get(node.getCriteria().get(0).getRight());
+    if (rightTimeColumnPosition == null) {
+      throw new IllegalStateException("Right child of JoinNode doesn't contain 
time column");
     }
-    int rightTimeColumnPosition =
-        
node.getRightChild().getOutputSymbols().indexOf(node.getCriteria().get(0).getRight());
     int[] rightOutputSymbolIdx = new int[node.getRightOutputSymbols().size()];
     for (int i = 0; i < rightOutputSymbolIdx.length; i++) {
-      rightOutputSymbolIdx[i] =
-          
node.getRightChild().getOutputSymbols().indexOf(node.getRightOutputSymbols().get(i));
+      Integer index = 
rightColumnNamesMap.get(node.getRightOutputSymbols().get(i));
+      if (index == null) {
+        throw new IllegalStateException(
+            "Right child of JoinNode doesn't contain RightOutputSymbol "
+                + node.getLeftOutputSymbols().get(i));
+      }
+      rightOutputSymbolIdx[i] = index;
     }
 
     if (requireNonNull(node.getJoinType()) == JoinNode.JoinType.INNER) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableDistributedPlanGenerator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableDistributedPlanGenerator.java
index 6c1becfcc9c..1dddc807321 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableDistributedPlanGenerator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableDistributedPlanGenerator.java
@@ -86,7 +86,6 @@ import static 
org.apache.iotdb.db.queryengine.plan.relational.planner.optimizati
 import static 
org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations.TransformSortToStreamSort.isOrderByAllIdsAndTime;
 import static 
org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations.Util.split;
 import static 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.TableBuiltinScalarFunction.DATE_BIN;
-import static org.apache.iotdb.db.utils.constant.TestConstant.TIMESTAMP_STR;
 import static org.apache.tsfile.utils.Preconditions.checkArgument;
 
 /** This class is used to generate distributed plan for table model. */
@@ -719,7 +718,7 @@ public class TableDistributedPlanGenerator
 
     boolean lastIsTimeRelated = false;
     for (final Symbol symbol : expectedOrderingScheme.getOrderBy()) {
-      if (timeRelatedSymbol(symbol)) {
+      if (timeRelatedSymbol(symbol, tableScanNode)) {
         if (!expectedOrderingScheme.getOrderings().get(symbol).isAscending()) {
           // TODO(beyyes) move scan order judgement into logical plan optimizer
           resultTableScanNodeList.forEach(
@@ -864,8 +863,8 @@ public class TableDistributedPlanGenerator
   }
 
   // time column or push down date_bin function call in agg which should only 
have one such column
-  private boolean timeRelatedSymbol(Symbol symbol) {
-    return TIMESTAMP_STR.equalsIgnoreCase(symbol.getName())
+  private boolean timeRelatedSymbol(Symbol symbol, TableScanNode 
tableScanNode) {
+    return tableScanNode.isTimeColumn(symbol)
         || PUSH_DOWN_DATE_BIN_SYMBOL_NAME.equals(symbol.getName());
   }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableModelTypeProviderExtractor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableModelTypeProviderExtractor.java
index 7d78f4b5a46..ccbaddc28c4 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableModelTypeProviderExtractor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableModelTypeProviderExtractor.java
@@ -231,6 +231,11 @@ public class TableModelTypeProviderExtractor {
     @Override
     public Void visitExchange(ExchangeNode node, Void context) {
       node.getChildren().forEach(c -> c.accept(this, context));
+      node.getOutputSymbols()
+          .forEach(
+              symbol ->
+                  beTypeProvider.putTableModelType(
+                      symbol, feTypeProvider.getTableModelType(symbol)));
       return null;
     }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/iterative/rule/PruneTableScanColumns.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/iterative/rule/PruneTableScanColumns.java
index 2bd37ea1a20..7275f977014 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/iterative/rule/PruneTableScanColumns.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/iterative/rule/PruneTableScanColumns.java
@@ -13,7 +13,6 @@
  */
 package org.apache.iotdb.db.queryengine.plan.relational.planner.iterative.rule;
 
-import org.apache.iotdb.db.queryengine.plan.expression.leaf.TimestampOperand;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
 import org.apache.iotdb.db.queryengine.plan.relational.metadata.ColumnSchema;
 import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
@@ -25,7 +24,6 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.planner.node.TableScanNod
 import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
@@ -73,12 +71,10 @@ public class PruneTableScanColumns extends 
ProjectOffPushDownRule<TableScanNode>
     // add time entry if TimePredicate exists
     node.getTimePredicate()
         .ifPresent(
-            timePredicate -> {
-              Symbol time =
-                  Symbol.of(
-                      
TimestampOperand.TIMESTAMP_EXPRESSION_STRING.toLowerCase(Locale.ENGLISH));
-              newAssignments.put(time, node.getAssignments().get(time));
-            });
+            timePredicate ->
+                SymbolsExtractor.extractUnique(timePredicate)
+                    .forEach(
+                        symbol -> newAssignments.put(symbol, 
node.getAssignments().get(symbol))));
 
     return Optional.of(
         new TableScanNode(
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 d505b60e3b2..8054f94404f 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
@@ -198,6 +198,24 @@ public class TableScanNode extends SourceNode {
             || columnSchema.getColumnCategory() == TIME);
   }
 
+  public boolean isTimeColumn(Symbol symbol) {
+    return isTimeColumn(symbol, assignments);
+  }
+
+  public Optional<Symbol> getTimeColumn() {
+    for (Map.Entry<Symbol, ColumnSchema> entry : assignments.entrySet()) {
+      if (entry.getValue().getColumnCategory() == TIME) {
+        return Optional.of(entry.getKey());
+      }
+    }
+    return Optional.empty();
+  }
+
+  public static boolean isTimeColumn(Symbol symbol, Map<Symbol, ColumnSchema> 
columnSchemaMap) {
+    ColumnSchema columnSchema = columnSchemaMap.get(symbol);
+    return columnSchema != null && columnSchema.getColumnCategory() == TIME;
+  }
+
   @Override
   protected void serializeAttributes(ByteBuffer byteBuffer) {
     PlanNodeType.TABLE_SCAN_NODE.serialize(byteBuffer);
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/PushAggregationIntoTableScan.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/PushAggregationIntoTableScan.java
index ecdef92b6b4..1446d48bb2b 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/PushAggregationIntoTableScan.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/PushAggregationIntoTableScan.java
@@ -16,7 +16,6 @@ package 
org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations;
 
 import org.apache.iotdb.db.queryengine.common.QueryId;
 import org.apache.iotdb.db.queryengine.common.SessionInfo;
-import org.apache.iotdb.db.queryengine.plan.expression.leaf.TimestampOperand;
 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.metadata.Metadata;
@@ -171,7 +170,9 @@ public class PushAggregationIntoTableScan implements 
PlanOptimizer {
                       hasProject
                               && !(assignments.get(groupingKey) instanceof 
SymbolReference
                                   || isDateBinFunctionOfTime(
-                                      assignments.get(groupingKey), 
dateBinFunctionsOfTime))
+                                      assignments.get(groupingKey),
+                                      dateBinFunctionsOfTime,
+                                      tableScanNode))
                           || 
tableScanNode.isMeasurementOrTimeColumn(groupingKey))
           || dateBinFunctionsOfTime.size() > 1) {
         // If expr except date_bin(time), Measurement column, or Time column 
appears in
@@ -192,15 +193,16 @@ public class PushAggregationIntoTableScan implements 
PlanOptimizer {
     }
 
     private boolean isDateBinFunctionOfTime(
-        Expression expression, List<FunctionCall> dateBinFunctionsOfTime) {
+        Expression expression,
+        List<FunctionCall> dateBinFunctionsOfTime,
+        TableScanNode tableScanNode) {
       if (expression instanceof FunctionCall) {
         FunctionCall function = (FunctionCall) expression;
         if (TableBuiltinScalarFunction.DATE_BIN
                 .getFunctionName()
                 .equals(function.getName().toString())
             && function.getArguments().get(2) instanceof SymbolReference
-            && TimestampOperand.TIMESTAMP_EXPRESSION_STRING.equalsIgnoreCase(
-                ((SymbolReference) function.getArguments().get(2)).getName())) 
{
+            && 
tableScanNode.isTimeColumn(Symbol.from(function.getArguments().get(2)))) {
           dateBinFunctionsOfTime.add(function);
           return true;
         }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/PushLimitOffsetIntoTableScan.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/PushLimitOffsetIntoTableScan.java
index c6154d5ac55..ad612c18bdc 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/PushLimitOffsetIntoTableScan.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/PushLimitOffsetIntoTableScan.java
@@ -41,7 +41,6 @@ import java.util.Map;
 import java.util.Set;
 
 import static 
org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations.PushPredicateIntoTableScan.containsDiffFunction;
-import static org.apache.iotdb.db.utils.constant.TestConstant.TIMESTAMP_STR;
 
 /**
  * <b>Optimization phase:</b> Distributed plan planning.
@@ -183,7 +182,7 @@ public class PushLimitOffsetIntoTableScan implements 
PlanOptimizer {
           
analysis.getTableColumnSchema(tableScanNode.getQualifiedObjectName());
       Set<Symbol> sortSymbols = new HashSet<>();
       for (Symbol orderBy : orderingScheme.getOrderBy()) {
-        if (TIMESTAMP_STR.equalsIgnoreCase(orderBy.getName())) {
+        if (tableScanNode.isTimeColumn(orderBy)) {
           break;
         }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/SortElimination.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/SortElimination.java
index e69c559b8ef..d1f249010d9 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/SortElimination.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/SortElimination.java
@@ -22,6 +22,7 @@ package 
org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations;
 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.planner.OrderingScheme;
+import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol;
 import org.apache.iotdb.db.queryengine.plan.relational.planner.node.FillNode;
 import 
org.apache.iotdb.db.queryengine.plan.relational.planner.node.GapFillNode;
 import org.apache.iotdb.db.queryengine.plan.relational.planner.node.SortNode;
@@ -31,8 +32,6 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.planner.node.ValueFillNod
 
 import java.util.Collections;
 
-import static org.apache.iotdb.db.utils.constant.TestConstant.TIMESTAMP_STR;
-
 /**
  * <b>Optimization phase:</b> Distributed plan planning.
  *
@@ -71,7 +70,7 @@ public class SortElimination implements PlanOptimizer {
       OrderingScheme orderingScheme = node.getOrderingScheme();
       if (!context.hasSeenFill()
           && newContext.getTotalDeviceEntrySize() == 1
-          && 
TIMESTAMP_STR.equalsIgnoreCase(orderingScheme.getOrderBy().get(0).getName())) {
+          && 
orderingScheme.getOrderBy().get(0).getName().equals(context.getTimeColumnName()))
 {
         return child;
       }
       return !context.hasSeenFill() && node.isOrderByAllIdsAndTime()
@@ -95,6 +94,7 @@ public class SortElimination implements PlanOptimizer {
     @Override
     public PlanNode visitTableScan(TableScanNode node, Context context) {
       context.addDeviceEntrySize(node.getDeviceEntries().size());
+      
context.setTimeColumnName(node.getTimeColumn().map(Symbol::getName).orElse(null));
       return node;
     }
 
@@ -125,6 +125,8 @@ public class SortElimination implements PlanOptimizer {
     // has seen linear fill, previous fill or gapfill
     private boolean hasSeenFill = false;
 
+    private String timeColumnName = null;
+
     Context() {}
 
     public void addDeviceEntrySize(int deviceEntrySize) {
@@ -142,5 +144,13 @@ public class SortElimination implements PlanOptimizer {
     public void setHasSeenFill(boolean hasSeenFill) {
       this.hasSeenFill = hasSeenFill;
     }
+
+    public String getTimeColumnName() {
+      return timeColumnName;
+    }
+
+    public void setTimeColumnName(String timeColumnName) {
+      this.timeColumnName = timeColumnName;
+    }
   }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/TransformSortToStreamSort.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/TransformSortToStreamSort.java
index f5b0517c392..95f8004d8f8 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/TransformSortToStreamSort.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/TransformSortToStreamSort.java
@@ -35,7 +35,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.planner.node.TableScanNod
 
 import java.util.Map;
 
-import static 
org.apache.iotdb.db.queryengine.plan.expression.leaf.TimestampOperand.TIMESTAMP_EXPRESSION_STRING;
+import static 
org.apache.iotdb.db.queryengine.plan.relational.planner.node.TableScanNode.isTimeColumn;
 
 /**
  * <b>Optimization phase:</b> Logical plan planning.
@@ -150,8 +150,7 @@ public class TransformSortToStreamSort implements 
PlanOptimizer {
       }
     }
     return orderingScheme.getOrderings().size() == streamSortIndex + 1
-        || TIMESTAMP_EXPRESSION_STRING.equalsIgnoreCase(
-            orderingScheme.getOrderBy().get(streamSortIndex + 1).getName());
+        || isTimeColumn(orderingScheme.getOrderBy().get(streamSortIndex + 1), 
tableColumnSchema);
   }
 
   private static class Context {
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/JoinTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/JoinTest.java
index 13652a7c9c7..bc09310e46a 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/JoinTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/JoinTest.java
@@ -102,7 +102,7 @@ public class JoinTest {
         new TableLogicalPlanner(QUERY_CONTEXT, TEST_MATADATA, SESSION_INFO, 
DEFAULT_WARNING)
             .plan(analysis);
 
-    // LogicalPlan: `Output-Offset-Limit-Join-(Left + 
Right)-Sort-(Project)-TableScan`
+    // LogicalPlan: `Output-Offset-Limit-Join-(Left + Right)-Sort-TableScan`
     logicalPlanNode = logicalQueryPlan.getRootNode();
     assertNodeMatches(
         logicalPlanNode, OutputNode.class, OffsetNode.class, LimitNode.class, 
JoinNode.class);
@@ -124,9 +124,8 @@ public class JoinTest {
     TableScanNode leftTableScanNode = (TableScanNode) 
getChildrenNode(leftSortNode, 1);
     assertTableScan(leftTableScanNode, ALL_DEVICE_ENTRIES, Ordering.ASC, 0, 0, 
true, "");
     SortNode rightSortNode = (SortNode) joinNode.getRightChild();
-    assertTrue(getChildrenNode(rightSortNode, 1) instanceof ProjectNode);
-    assertTrue(getChildrenNode(rightSortNode, 2) instanceof TableScanNode);
-    TableScanNode rightTableScanNode = (TableScanNode) 
getChildrenNode(rightSortNode, 2);
+    assertTrue(getChildrenNode(rightSortNode, 1) instanceof TableScanNode);
+    TableScanNode rightTableScanNode = (TableScanNode) 
getChildrenNode(rightSortNode, 1);
     assertTableScan(rightTableScanNode, ALL_DEVICE_ENTRIES, Ordering.ASC, 0, 
0, true, "");
 
     /*
@@ -143,8 +142,7 @@ public class JoinTest {
      *                   └──MergeSortNode-128
      *                       ├──ExchangeNode-174: 
[SourceAddress:192.0.12.1/test_query.2.0/176]
      *                       ├──SortNode-130
-     *                       │   └──ProjectNode-126
-     *                       │       └──TableScanNode-123
+     *                       │   └──TableScanNode-126
      *                       └──ExchangeNode-175: 
[SourceAddress:192.0.10.1/test_query.3.0/177]
      *
      * IdentitySinkNode-201
@@ -157,13 +155,11 @@ public class JoinTest {
      *
      * IdentitySinkNode-203
      *   └──SortNode-154
-     *       └──ProjectNode-150
-     *           └──TableScanNode-147
+     *       └──TableScanNode-150
      *
      * IdentitySinkNode-203
      *   └──SortNode-154
-     *       └──ProjectNode-150
-     *           └──TableScanNode-147
+     *       └──TableScanNode-150
      */
     distributedQueryPlan = new TableDistributedPlanner(analysis, 
logicalQueryPlan).plan();
     assertEquals(5, distributedQueryPlan.getFragments().size());
@@ -189,9 +185,8 @@ public class JoinTest {
     identitySinkNode =
         (IdentitySinkNode) 
distributedQueryPlan.getFragments().get(3).getPlanNodeTree();
     assertTrue(getChildrenNode(identitySinkNode, 1) instanceof SortNode);
-    assertTrue(getChildrenNode(identitySinkNode, 2) instanceof ProjectNode);
-    assertTrue(getChildrenNode(identitySinkNode, 3) instanceof TableScanNode);
-    tableScanNode = (TableScanNode) getChildrenNode(identitySinkNode, 3);
+    assertTrue(getChildrenNode(identitySinkNode, 2) instanceof TableScanNode);
+    tableScanNode = (TableScanNode) getChildrenNode(identitySinkNode, 2);
     assertTableScan(tableScanNode, SHENZHEN_DEVICE_ENTRIES, Ordering.ASC, 0, 
0, true, "");
   }
 
@@ -279,9 +274,8 @@ public class JoinTest {
     TableScanNode leftTableScanNode = (TableScanNode) 
getChildrenNode(leftSortNode, 1);
     assertTableScan(leftTableScanNode, BEIJING_A1_DEVICE_ENTRY, Ordering.ASC, 
0, 0, true, "");
     SortNode rightSortNode = (SortNode) joinNode.getRightChild();
-    assertTrue(getChildrenNode(rightSortNode, 1) instanceof ProjectNode);
-    assertTrue(getChildrenNode(rightSortNode, 2) instanceof TableScanNode);
-    TableScanNode rightTableScanNode = (TableScanNode) 
getChildrenNode(rightSortNode, 2);
+    assertTrue(getChildrenNode(rightSortNode, 1) instanceof TableScanNode);
+    TableScanNode rightTableScanNode = (TableScanNode) 
getChildrenNode(rightSortNode, 1);
     assertTableScan(rightTableScanNode, SHENZHEN_DEVICE_ENTRIES, Ordering.ASC, 
0, 0, true, "");
 
     /*
@@ -294,8 +288,7 @@ public class JoinTest {
      *                       ├──ExchangeNode-193: 
[SourceAddress:192.0.10.1/test_query.2.0/195]
      *                       └──MergeSortNode-165
      *                           ├──SortNode-166
-     *                           │   └──ProjectNode-163
-     *                           │       └──TableScanNode-161
+     *                           │   └──TableScanNode-163
      *                           └──ExchangeNode-194: 
[SourceAddress:192.0.11.1/test_query.3.0/196]
      *
      *  IdentitySinkNode-195
@@ -303,8 +296,7 @@ public class JoinTest {
      *
      *  IdentitySinkNode-196
      *   └──SortNode-167
-     *       └──ProjectNode-164
-     *           └──TableScanNode-162
+     *       └──TableScanNode-164
      */
     distributedQueryPlan = new TableDistributedPlanner(analysis, 
logicalQueryPlan).plan();
     assertEquals(3, distributedQueryPlan.getFragments().size());
@@ -315,9 +307,8 @@ public class JoinTest {
     assertTrue(joinNode.getLeftChild() instanceof ExchangeNode);
     assertTrue(joinNode.getRightChild() instanceof MergeSortNode);
     mergeSortNode = (MergeSortNode) joinNode.getRightChild();
-    assertNodeMatches(
-        mergeSortNode, MergeSortNode.class, SortNode.class, ProjectNode.class, 
TableScanNode.class);
-    tableScanNode = (TableScanNode) getChildrenNode(mergeSortNode, 3);
+    assertNodeMatches(mergeSortNode, MergeSortNode.class, SortNode.class, 
TableScanNode.class);
+    tableScanNode = (TableScanNode) getChildrenNode(mergeSortNode, 2);
     assertTableScan(tableScanNode, SHENZHEN_DEVICE_ENTRIES, Ordering.ASC, 0, 
0, true, "");
 
     identitySinkNode =
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestUtils.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestUtils.java
index ef4f5fdefc0..62fb31b7b55 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestUtils.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestUtils.java
@@ -41,6 +41,7 @@ import org.junit.Assert;
 import java.time.ZoneId;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -127,8 +128,9 @@ public class TestUtils {
       List<Symbol> rightOutputSymbols) {
     assertEquals(joinType, joinNode.getJoinType());
     assertEquals(joinCriteria, joinNode.getCriteria());
-    assertEquals(leftOutputSymbols, joinNode.getLeftOutputSymbols());
-    assertEquals(rightOutputSymbols, joinNode.getRightOutputSymbols());
+    assertEquals(new HashSet<>(leftOutputSymbols), new 
HashSet<>(joinNode.getLeftOutputSymbols()));
+    assertEquals(
+        new HashSet<>(rightOutputSymbols), new 
HashSet<>(joinNode.getRightOutputSymbols()));
   }
 
   public static void assertNodeMatches(PlanNode node, Class... classes) {

Reply via email to