You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ja...@apache.org on 2025/05/21 06:00:24 UTC

(iotdb) branch master updated: NonAlignedTreeDeviceViewScan may return limit + offset lines result when the offset is pushed down

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 1cd4bc3c1bf NonAlignedTreeDeviceViewScan may return limit + offset lines result when the offset is pushed down
1cd4bc3c1bf is described below

commit 1cd4bc3c1bf746c14c44eeb6e00ae4217fec0c37
Author: shuwenwei <55...@users.noreply.github.com>
AuthorDate: Wed May 21 14:00:17 2025 +0800

    NonAlignedTreeDeviceViewScan may return limit + offset lines result when the offset is pushed down
---
 .../plan/planner/TableOperatorGenerator.java       | 13 +++++++-----
 ...nAlignedTreeDeviceViewScanOperatorTreeTest.java | 23 ++++++++++++++++++++++
 2 files changed, 31 insertions(+), 5 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 30087ebfbdc..d067f7cb84b 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
@@ -547,13 +547,13 @@ public class TableOperatorGenerator extends PlanVisitor<Operator, LocalExecution
             boolean canPushDownLimitToAllSeriesScanOptions =
                 canPushDownLimit && pushDownConjunctsForEachMeasurement.isEmpty();
             // the left child of LeftOuterTimeJoinOperator is SeriesScanOperator
-            boolean pushDownLimitToLeftChildSeriesScanOperator =
+            boolean pushDownOffsetAndLimitToLeftChildSeriesScanOperator =
                 canPushDownLimit && pushDownConjunctsForEachMeasurement.size() == 1;
             // the left child of LeftOuterTimeJoinOperator is InnerTimeJoinOperator
             boolean pushDownOffsetAndLimitAfterInnerJoinOperator =
                 canPushDownLimit && pushDownConjunctsForEachMeasurement.size() > 1;
             removeUpperOffsetAndLimitOperator =
-                pushDownLimitToLeftChildSeriesScanOperator
+                pushDownOffsetAndLimitToLeftChildSeriesScanOperator
                     || pushDownOffsetAndLimitAfterInnerJoinOperator
                     || isSingleColumn;
             for (int i = 0; i < measurementSchemas.size(); i++) {
@@ -580,16 +580,19 @@ public class TableOperatorGenerator extends PlanVisitor<Operator, LocalExecution
                         commonParameter.timeColumnName));
               }
               if (isSingleColumn
-                  || (pushDownLimitToLeftChildSeriesScanOperator
+                  || (pushDownOffsetAndLimitToLeftChildSeriesScanOperator
                       && pushDownPredicateForCurrentMeasurement != null)) {
                 builder.withPushDownLimit(node.getPushDownLimit());
                 builder.withPushLimitToEachDevice(node.isPushLimitToEachDevice());
               }
-              if (canPushDownLimitToAllSeriesScanOptions) {
+
+              // In the case of single column, both offset and limit are pushed down to the
+              // SeriesScanOperator
+              if (!isSingleColumn && canPushDownLimitToAllSeriesScanOptions) {
                 builder.withPushDownLimit(node.getPushDownLimit() + node.getPushDownOffset());
               }
               if (isSingleColumn
-                  || (pushDownLimitToLeftChildSeriesScanOperator
+                  || (pushDownOffsetAndLimitToLeftChildSeriesScanOperator
                       && pushDownPredicateForCurrentMeasurement != null)) {
                 builder.withPushDownOffset(
                     node.isPushLimitToEachDevice() ? 0 : node.getPushDownOffset());
diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/NonAlignedTreeDeviceViewScanOperatorTreeTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/NonAlignedTreeDeviceViewScanOperatorTreeTest.java
index 44f94df94f0..e5cfb1c2b2f 100644
--- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/NonAlignedTreeDeviceViewScanOperatorTreeTest.java
+++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/NonAlignedTreeDeviceViewScanOperatorTreeTest.java
@@ -273,6 +273,29 @@ public class NonAlignedTreeDeviceViewScanOperatorTreeTest {
     }
   }
 
+  @Test
+  public void testScanSingleFieldColumnWithPushLimitToEachDevice1() throws Exception {
+    List<String> outputColumnList = Arrays.asList("sensor0");
+    TreeNonAlignedDeviceViewScanNode node =
+        getTreeNonAlignedDeviceViewScanNode(outputColumnList, Arrays.asList("sensor0"));
+    node.setPushLimitToEachDevice(false);
+    node.setPushDownLimit(1);
+    node.setPushDownOffset(1);
+    ExecutorService instanceNotificationExecutor =
+        IoTDBThreadPoolFactory.newFixedThreadPool(1, "test-instance-notification");
+    Operator operator = getOperator(node, instanceNotificationExecutor);
+    assertTrue(operator instanceof DeviceIteratorScanOperator);
+    try {
+      checkResult(operator, outputColumnList, 1);
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    } finally {
+      operator.close();
+      instanceNotificationExecutor.shutdown();
+    }
+  }
+
   @Test
   public void testScanWithPushDownPredicateAndPushLimitToEachDevice1() throws Exception {
     List<String> outputColumnList = Arrays.asList("sensor0", "sensor1", "sensor2", "time", "tag1");