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 e1bd11b9d6e Fixed the issue with deeply nested Or Filter in
NonAlignedTreeViewScan
e1bd11b9d6e is described below
commit e1bd11b9d6e9cd1109a2f16af0157cd734824666
Author: shuwenwei <[email protected]>
AuthorDate: Mon Jun 23 19:34:31 2025 +0800
Fixed the issue with deeply nested Or Filter in NonAlignedTreeViewScan
---
.../plan/planner/TableOperatorGenerator.java | 20 ++++++++---
...nAlignedTreeDeviceViewScanOperatorTreeTest.java | 39 ++++++++++++++++++++++
2 files changed, 55 insertions(+), 4 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 2132df0af1d..8c5143833e4 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
@@ -597,6 +597,19 @@ public class TableOperatorGenerator extends
PlanVisitor<Operator, LocalExecution
}
}
+ // Using getSeriesScanOptionsBuilder to create SeriesScanBuilder
will cause multiple
+ // calls to setTimeFilterForTableModel and generate a deeply
nested Or filter.
+ // Therefore, a separate setting is made here
+ Filter timeFilter = null;
+ if (node.getTimePredicate().isPresent()) {
+ Expression timePredicate = node.getTimePredicate().get();
+ timeFilter = timePredicate.accept(new
ConvertPredicateToTimeFilterVisitor(), null);
+ context
+ .getDriverContext()
+ .getFragmentInstanceContext()
+ .setTimeFilterForTableModel(timeFilter);
+ }
+
boolean canPushDownLimit = cannotPushDownConjuncts.isEmpty();
// only use full outer time join
boolean canPushDownLimitToAllSeriesScanOptions =
@@ -621,10 +634,9 @@ public class TableOperatorGenerator extends
PlanVisitor<Operator, LocalExecution
: (pushDownPredicatesForCurrentMeasurement == null
? null
:
IrUtils.combineConjuncts(pushDownPredicatesForCurrentMeasurement));
- SeriesScanOptions.Builder builder =
- node.getTimePredicate()
- .map(expression -> getSeriesScanOptionsBuilder(context,
expression))
- .orElseGet(SeriesScanOptions.Builder::new);
+ SeriesScanOptions.Builder builder = new
SeriesScanOptions.Builder();
+ // time filter may be stateful, so we need to copy it
+ builder.withGlobalTimeFilter(timeFilter == null ? null :
timeFilter.copy());
builder
.withIsTableViewForTreeModel(true)
.withAllSensors(new HashSet<>(measurementColumnNames));
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 73f957ddf78..2188a04479b 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
@@ -67,6 +67,8 @@ import org.apache.tsfile.read.common.block.TsBlock;
import org.apache.tsfile.read.common.type.Type;
import org.apache.tsfile.read.common.type.TypeEnum;
import org.apache.tsfile.read.common.type.TypeFactory;
+import org.apache.tsfile.read.filter.basic.Filter;
+import org.apache.tsfile.read.filter.operator.Or;
import org.apache.tsfile.utils.Binary;
import org.apache.tsfile.write.schema.IMeasurementSchema;
import org.junit.After;
@@ -86,6 +88,7 @@ import java.util.stream.Collectors;
import static
org.apache.iotdb.db.queryengine.execution.fragment.FragmentInstanceContext.createFragmentInstanceContext;
import static
org.apache.iotdb.db.queryengine.execution.operator.Operator.NOT_BLOCKED;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -199,6 +202,37 @@ public class NonAlignedTreeDeviceViewScanOperatorTreeTest {
}
}
+ @Test
+ public void testScanWithPushDownPredicateAndLimitAndOffsetAndTimePredicate()
throws Exception {
+ List<String> outputColumnList = Arrays.asList("sensor0", "sensor1",
"sensor2", "time", "tag1");
+ TreeNonAlignedDeviceViewScanNode node =
getTreeNonAlignedDeviceViewScanNode(outputColumnList);
+ node.setPushDownOffset(500);
+ node.setPushDownLimit(500);
+ node.setTimePredicate(
+ new ComparisonExpression(
+ ComparisonExpression.Operator.GREATER_THAN,
+ new Symbol("time").toSymbolReference(),
+ new LongLiteral("0")));
+ node.setPushDownPredicate(
+ new ComparisonExpression(
+ ComparisonExpression.Operator.GREATER_THAN,
+ new Symbol("sensor1").toSymbolReference(),
+ new LongLiteral("1000")));
+ ExecutorService instanceNotificationExecutor =
+ IoTDBThreadPoolFactory.newFixedThreadPool(1,
"test-instance-notification");
+ Operator operator = getOperator(node, instanceNotificationExecutor);
+ assertTrue(operator instanceof DeviceIteratorScanOperator);
+ try {
+ checkResult(operator, outputColumnList, 500);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ } finally {
+ operator.close();
+ instanceNotificationExecutor.shutdown();
+ }
+ }
+
@Test
public void testScanWithPushDownPredicateAndPushLimitToEachDevice() throws
Exception {
List<String> outputColumnList = Arrays.asList("sensor0", "sensor1",
"sensor2", "time", "tag1");
@@ -633,6 +667,11 @@ public class NonAlignedTreeDeviceViewScanOperatorTreeTest {
}
count += tsBlock.getPositionCount();
}
+ FragmentInstanceContext fragmentInstance =
operator.getOperatorContext().getInstanceContext();
+ Filter globalTimeFilter = fragmentInstance.getGlobalTimeFilter();
+ if (globalTimeFilter != null) {
+ assertFalse(globalTimeFilter instanceof Or);
+ }
assertEquals(expectedCount, count);
}