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 edc684e61e0 Fix the usage of idAndAttributeIndexMap in TableScanNode
edc684e61e0 is described below

commit edc684e61e0fa6879fc3df0490f7d1295d00cb10
Author: Beyyes <[email protected]>
AuthorDate: Fri Aug 16 09:29:22 2024 +0800

    Fix the usage of idAndAttributeIndexMap in TableScanNode
---
 ...ava => IoTDBMultiIDsWithAttributesTableIT.java} | 110 ++++++++++++++++++++-
 .../plan/relational/planner/RelationPlanner.java   |   4 +-
 .../relational/planner/node/TableScanNode.java     |   4 -
 .../optimizations/PushPredicateIntoTableScan.java  |  44 +++++----
 .../plan/relational/analyzer/AnalyzerTest.java     |  16 ++-
 .../plan/relational/analyzer/SortTest.java         |   9 +-
 6 files changed, 142 insertions(+), 45 deletions(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/orderBy/IoTDBStreamSortIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/orderBy/IoTDBMultiIDsWithAttributesTableIT.java
similarity index 74%
rename from 
integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/orderBy/IoTDBStreamSortIT.java
rename to 
integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/orderBy/IoTDBMultiIDsWithAttributesTableIT.java
index ddcbb3ecabc..c2528c32193 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/orderBy/IoTDBStreamSortIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/orderBy/IoTDBMultiIDsWithAttributesTableIT.java
@@ -36,13 +36,12 @@ import java.sql.Statement;
 import static org.apache.iotdb.db.it.utils.TestUtils.tableResultSetEqualTest;
 import static org.junit.Assert.fail;
 
+/** In this IT, table has more than one IDs and Attributes. */
 @RunWith(IoTDBTestRunner.class)
 @Category({LocalStandaloneIT.class, ClusterIT.class})
-public class IoTDBStreamSortIT {
+public class IoTDBMultiIDsWithAttributesTableIT {
   private static final String DATABASE_NAME = "db";
 
-  // the data can be viewed in
-  // 
https://docs.google.com/spreadsheets/d/1OWA1bKraArCwWVnuTjuhJ5yLG0PFLdD78gD6FjquepI/edit#gid=0
   private static final String[] sql1 =
       new String[] {
         "CREATE DATABASE db",
@@ -113,6 +112,111 @@ public class IoTDBStreamSortIT {
     }
   }
 
+  @Test
+  public void onlyQueryAttribute2Test() {
+    String[] expectedHeader =
+        new String[] {
+          "time", "device", "attr2", "num", "str",
+        };
+    String[] retArray =
+        new String[] {
+          "1970-01-01T00:00:00.000Z,d1,d,3,coconut,",
+          "1970-01-01T00:00:00.000Z,d2,c,3,coconut,",
+          "1970-01-01T00:00:00.020Z,d1,zz,2,pineapple,",
+          "1970-01-01T00:00:00.020Z,d2,null,2,pineapple,",
+          "1970-01-01T00:00:00.040Z,d1,a,1,apricot,",
+          "1970-01-01T00:00:00.040Z,d2,null,1,apricot,",
+          "1970-01-01T00:00:00.080Z,d1,null,9,apple,",
+          "1970-01-01T00:00:00.080Z,d2,null,9,apple,",
+          "1970-01-01T00:00:00.100Z,d1,null,8,papaya,",
+          "1970-01-01T00:00:00.100Z,d2,null,8,papaya,",
+          "1971-01-01T00:00:00.000Z,d1,d,6,banana,",
+          "1971-01-01T00:00:00.000Z,d2,c,6,banana,",
+          "1971-01-01T00:00:00.100Z,d1,zz,10,pumelo,",
+          "1971-01-01T00:00:00.100Z,d2,null,10,pumelo,",
+          "1971-01-01T00:00:00.500Z,d1,a,4,peach,",
+          "1971-01-01T00:00:00.500Z,d2,null,4,peach,",
+          "1971-01-01T00:00:01.000Z,d1,null,5,orange,",
+          "1971-01-01T00:00:01.000Z,d2,null,5,orange,",
+          "1971-01-01T00:00:10.000Z,d1,null,7,lemon,",
+          "1971-01-01T00:00:10.000Z,d2,null,7,lemon,",
+          "1971-01-01T00:01:40.000Z,d1,d,11,pitaya,",
+          "1971-01-01T00:01:40.000Z,d2,c,11,pitaya,",
+          "1971-04-26T17:46:40.000Z,d1,zz,12,strawberry,",
+          "1971-04-26T17:46:40.000Z,d2,null,12,strawberry,",
+          "1971-04-26T17:46:40.020Z,d1,a,14,cherry,",
+          "1971-04-26T17:46:40.020Z,d2,null,14,cherry,",
+          "1971-04-26T18:01:40.000Z,d1,null,13,lychee,",
+          "1971-04-26T18:01:40.000Z,d2,null,13,lychee,",
+          "1971-08-20T11:33:20.000Z,d1,null,15,watermelon,",
+          "1971-08-20T11:33:20.000Z,d2,null,15,watermelon,",
+        };
+    tableResultSetEqualTest(
+        "select time, device, attr2, num, str from table0 order by time, 
device",
+        expectedHeader,
+        retArray,
+        DATABASE_NAME);
+
+    expectedHeader =
+        new String[] {
+          "time", "num", "str",
+        };
+    retArray =
+        new String[] {
+          "1970-01-01T00:00:00.040Z,1,apricot,",
+          "1971-01-01T00:00:00.500Z,4,peach,",
+          "1971-04-26T17:46:40.020Z,14,cherry,",
+          "1970-01-01T00:00:00.000Z,3,coconut,",
+          "1971-01-01T00:00:00.000Z,6,banana,",
+          "1971-01-01T00:01:40.000Z,11,pitaya,",
+          "1970-01-01T00:00:00.000Z,3,coconut,",
+          "1971-01-01T00:00:00.000Z,6,banana,",
+          "1971-01-01T00:01:40.000Z,11,pitaya,",
+          "1970-01-01T00:00:00.020Z,2,pineapple,",
+          "1971-01-01T00:00:00.100Z,10,pumelo,",
+          "1971-04-26T17:46:40.000Z,12,strawberry,",
+          "1970-01-01T00:00:00.100Z,8,papaya,",
+          "1970-01-01T00:00:00.080Z,9,apple,",
+          "1971-01-01T00:00:10.000Z,7,lemon,",
+          "1971-01-01T00:00:01.000Z,5,orange,",
+          "1971-08-20T11:33:20.000Z,15,watermelon,",
+          "1971-04-26T18:01:40.000Z,13,lychee,",
+          "1970-01-01T00:00:00.020Z,2,pineapple,",
+          "1970-01-01T00:00:00.040Z,1,apricot,",
+          "1971-01-01T00:00:00.100Z,10,pumelo,",
+          "1971-01-01T00:00:00.500Z,4,peach,",
+          "1971-04-26T17:46:40.000Z,12,strawberry,",
+          "1971-04-26T17:46:40.020Z,14,cherry,",
+          "1970-01-01T00:00:00.080Z,9,apple,",
+          "1970-01-01T00:00:00.100Z,8,papaya,",
+          "1971-01-01T00:00:01.000Z,5,orange,",
+          "1971-01-01T00:00:10.000Z,7,lemon,",
+          "1971-04-26T18:01:40.000Z,13,lychee,",
+          "1971-08-20T11:33:20.000Z,15,watermelon,",
+        };
+    tableResultSetEqualTest(
+        "select time, num, str from table0 order by attr2, device",
+        expectedHeader,
+        retArray,
+        DATABASE_NAME);
+
+    expectedHeader =
+        new String[] {
+          "time", "device", "num", "str",
+        };
+    retArray =
+        new String[] {
+          "1970-01-01T00:00:00.000Z,d1,3,coconut,",
+          "1971-01-01T00:00:00.000Z,d1,6,banana,",
+          "1971-01-01T00:01:40.000Z,d1,11,pitaya,",
+        };
+    tableResultSetEqualTest(
+        "select time, device, num, str from table0 where attr2 = 'd' order by 
time,device",
+        expectedHeader,
+        retArray,
+        DATABASE_NAME);
+  }
+
   @Test
   public void sortAttributeTest() {
     String[] expectedHeader =
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 9bc61233add..cdfb2023ae9 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
@@ -131,7 +131,7 @@ public class RelationPlanner extends 
AstVisitor<RelationPlan, Void> {
     // 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, attributeIndex = 0;
+    int idIndex = 0;
     for (Field field : fields) {
       Symbol symbol = symbolAllocator.newSymbol(field);
       outputSymbolsBuilder.add(symbol);
@@ -142,8 +142,6 @@ public class RelationPlanner extends 
AstVisitor<RelationPlan, Void> {
               field.getName().orElse(null), field.getType(), field.isHidden(), 
category));
       if (category == TsTableColumnCategory.ID) {
         idAndAttributeIndexMap.put(symbol, idIndex++);
-      } else if (category == TsTableColumnCategory.ATTRIBUTE) {
-        idAndAttributeIndexMap.put(symbol, attributeIndex++);
       }
     }
 
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 770ab775c05..0e575f5dbd5 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
@@ -371,10 +371,6 @@ public class TableScanNode extends SourceNode {
     this.outputSymbols = outputSymbols;
   }
 
-  public void setAssignments(Map<Symbol, ColumnSchema> assignments) {
-    this.assignments = assignments;
-  }
-
   public Map<Symbol, ColumnSchema> getAssignments() {
     return this.assignments;
   }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/PushPredicateIntoTableScan.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/PushPredicateIntoTableScan.java
index 0fc783013ce..6e738a1c4aa 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/PushPredicateIntoTableScan.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/PushPredicateIntoTableScan.java
@@ -30,6 +30,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.analyzer.Analysis;
 import 
org.apache.iotdb.db.queryengine.plan.relational.analyzer.predicate.ConvertPredicateToTimeFilterVisitor;
 import 
org.apache.iotdb.db.queryengine.plan.relational.analyzer.predicate.PredicateCombineIntoTableScanChecker;
 import 
org.apache.iotdb.db.queryengine.plan.relational.analyzer.predicate.PredicatePushIntoMetadataChecker;
+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.Metadata;
 import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol;
@@ -45,16 +46,17 @@ import org.apache.tsfile.utils.Pair;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
-import java.util.Locale;
+import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
 import static java.util.Objects.requireNonNull;
 import static 
org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory.ATTRIBUTE;
 import static 
org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory.MEASUREMENT;
+import static 
org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory.TIME;
 import static 
org.apache.iotdb.db.queryengine.plan.analyze.AnalyzeVisitor.getTimePartitionSlotList;
-import static 
org.apache.iotdb.db.queryengine.plan.expression.leaf.TimestampOperand.TIMESTAMP_EXPRESSION_STRING;
 import static 
org.apache.iotdb.db.queryengine.plan.relational.planner.ir.GlobalTimePredicateExtractVisitor.extractGlobalTimeFilter;
 
 /**
@@ -199,18 +201,18 @@ public class PushPredicateIntoTableScan implements 
PlanOptimizer {
     }
 
     private SplitExpression splitPredicate(TableScanNode node) {
-
-      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());
-      
measurementColumnNames.add(TIMESTAMP_EXPRESSION_STRING.toLowerCase(Locale.ENGLISH));
+      Set<String> idOrAttributeColumnNames = new 
HashSet<>(node.getAssignments().size());
+      Set<String> measurementColumnNames = new 
HashSet<>(node.getAssignments().size());
+      for (Map.Entry<Symbol, ColumnSchema> entry : 
node.getAssignments().entrySet()) {
+        Symbol columnSymbol = entry.getKey();
+        ColumnSchema columnSchema = entry.getValue();
+        if (MEASUREMENT.equals(columnSchema.getColumnCategory())
+            || TIME.equals(columnSchema.getColumnCategory())) {
+          measurementColumnNames.add(columnSymbol.getName());
+        } else {
+          idOrAttributeColumnNames.add(columnSymbol.getName());
+        }
+      }
 
       List<Expression> metadataExpressions = new ArrayList<>();
       List<Expression> expressionsCanPushDown = new ArrayList<>();
@@ -264,12 +266,14 @@ public class PushPredicateIntoTableScan implements 
PlanOptimizer {
 
     /** Get deviceEntries and DataPartition used in TableScan. */
     private void tableMetadataIndexScan(TableScanNode node, List<Expression> 
metadataExpressions) {
-      List<String> attributeColumns =
-          node.getOutputSymbols().stream()
-              .filter(
-                  symbol -> 
ATTRIBUTE.equals(node.getAssignments().get(symbol).getColumnCategory()))
-              .map(Symbol::getName)
-              .collect(Collectors.toList());
+      List<String> attributeColumns = new ArrayList<>();
+      int attributeIndex = 0;
+      for (Symbol columnName : node.getAssignments().keySet()) {
+        if 
(ATTRIBUTE.equals(node.getAssignments().get(columnName).getColumnCategory())) {
+          attributeColumns.add(columnName.getName());
+          node.getIdAndAttributeIndexMap().put(columnName, attributeIndex++);
+        }
+      }
       List<DeviceEntry> deviceEntries =
           metadata.indexScan(
               node.getQualifiedObjectName(), metadataExpressions, 
attributeColumns, queryContext);
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 34824d537bf..250208e6fd5 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
@@ -267,7 +267,7 @@ public class AnalyzerTest {
   @Test
   public void singleTableWithFilterTest2() {
     // measurement value filter, which can be pushed down to TableScanNode
-    sql = "SELECT tag1, attr1, s2 FROM table1 where s1 > 1";
+    sql = "SELECT tag1, attr2, s2 FROM table1 where s1 > 1";
     context = new MPPQueryContext(sql, queryId, sessionInfo, null, null);
     actualAnalysis = analyzeSQL(sql, metadata, context);
     assertNotNull(actualAnalysis);
@@ -282,16 +282,12 @@ public class AnalyzerTest {
     assertEquals("(\"s1\" > 1)", 
tableScanNode.getPushDownPredicate().toString());
     assertFalse(tableScanNode.getTimePredicate().isPresent());
     assertTrue(
-        Stream.of(
-                Symbol.of("tag1"),
-                Symbol.of("tag2"),
-                Symbol.of("tag3"),
-                Symbol.of("attr1"),
-                Symbol.of("attr2"))
+        Stream.of(Symbol.of("tag1"), Symbol.of("tag2"), Symbol.of("tag3"), 
Symbol.of("attr2"))
             .allMatch(tableScanNode.getIdAndAttributeIndexMap()::containsKey));
-    assertEquals(Arrays.asList("tag1", "attr1", "s2"), 
tableScanNode.getOutputColumnNames());
+    assertEquals(0, (int) 
tableScanNode.getIdAndAttributeIndexMap().get(Symbol.of("attr2")));
+    assertEquals(Arrays.asList("tag1", "attr2", "s2"), 
tableScanNode.getOutputColumnNames());
     assertEquals(
-        ImmutableSet.of("tag1", "attr1", "s1", "s2"),
+        ImmutableSet.of("tag1", "attr2", "s1", "s2"),
         tableScanNode.getAssignments().keySet().stream()
             .map(Symbol::toString)
             .collect(Collectors.toSet()));
@@ -581,7 +577,7 @@ public class AnalyzerTest {
     assertTrue(rootNode.getChildren().get(0) instanceof TableScanNode);
     tableScanNode = (TableScanNode) rootNode.getChildren().get(0);
     assertEquals(Arrays.asList("tag2", "attr2", "s2"), 
tableScanNode.getOutputColumnNames());
-    assertEquals(5, tableScanNode.getIdAndAttributeIndexMap().size());
+    assertEquals(4, tableScanNode.getIdAndAttributeIndexMap().size());
   }
 
   @Test
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/SortTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/SortTest.java
index 238bacc8180..e00e6bedd79 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/SortTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/SortTest.java
@@ -119,7 +119,7 @@ public class SortTest {
     assertEquals("testdb.table1", 
tableScanNode.getQualifiedObjectName().toString());
     assertEquals(8, tableScanNode.getAssignments().size());
     assertEquals(6, tableScanNode.getDeviceEntries().size());
-    assertEquals(5, tableScanNode.getIdAndAttributeIndexMap().size());
+    assertEquals(4, tableScanNode.getIdAndAttributeIndexMap().size());
     // TODO change scan order in logical plan
     assertEquals(ASC, tableScanNode.getScanOrder());
     assertEquals(0, tableScanNode.getPushDownLimit());
@@ -368,7 +368,7 @@ public class SortTest {
     assertEquals("testdb.table1", 
tableScanNode.getQualifiedObjectName().toString());
     assertEquals(8, tableScanNode.getAssignments().size());
     assertEquals(6, tableScanNode.getDeviceEntries().size());
-    assertEquals(5, tableScanNode.getIdAndAttributeIndexMap().size());
+    assertEquals(4, tableScanNode.getIdAndAttributeIndexMap().size());
     assertEquals(ASC, tableScanNode.getScanOrder());
     assertEquals(0, tableScanNode.getPushDownLimit());
     assertEquals(0, tableScanNode.getPushDownOffset());
@@ -448,7 +448,7 @@ public class SortTest {
     assertEquals("testdb.table1", 
tableScanNode.getQualifiedObjectName().toString());
     assertEquals(8, tableScanNode.getAssignments().size());
     assertEquals(6, tableScanNode.getDeviceEntries().size());
-    assertEquals(5, tableScanNode.getIdAndAttributeIndexMap().size());
+    assertEquals(4, tableScanNode.getIdAndAttributeIndexMap().size());
 
     // DistributePlan: optimize
     // 
`Output-Offset-Limit-Project-MergeSort-StreamSort-Project-Filter-TableScan`
@@ -614,7 +614,6 @@ public class SortTest {
     assertEquals("testdb.table1", 
tableScanNode.getQualifiedObjectName().toString());
     assertEquals(8, tableScanNode.getAssignments().size());
     assertEquals(6, tableScanNode.getDeviceEntries().size());
-    assertEquals(5, tableScanNode.getIdAndAttributeIndexMap().size());
     assertTrue(
         tableScanNode.getPushDownLimit() == expectedPushDownLimit
             && tableScanNode.getPushDownOffset() == expectedPushDownOffset);
@@ -683,7 +682,7 @@ public class SortTest {
     assertEquals("testdb.table1", 
tableScanNode.getQualifiedObjectName().toString());
     assertEquals(8, tableScanNode.getAssignments().size());
     assertEquals(6, tableScanNode.getDeviceEntries().size());
-    assertEquals(5, tableScanNode.getIdAndAttributeIndexMap().size());
+    assertEquals(4, tableScanNode.getIdAndAttributeIndexMap().size());
     assertEquals(expectedPushDownLimit, tableScanNode.getPushDownLimit());
     assertEquals(expectedPushDownOffset, tableScanNode.getPushDownOffset());
     assertEquals(isPushLimitToEachDevice, 
tableScanNode.isPushLimitToEachDevice());

Reply via email to