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

Wei-hao-Li pushed a commit to branch fix-time-partition
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit c71625d76486336246045b466593191be91a173b
Author: Weihao Li <[email protected]>
AuthorDate: Wed May 27 12:53:31 2026 +0800

    fix
    
    Signed-off-by: Weihao Li <[email protected]>
---
 .../it/query/IoTDBPredicateConversionTreeIT.java   | 50 ++++++++++++++++++++++
 .../queryengine/plan/analyze/AnalyzeVisitor.java   | 19 ++++----
 .../predicate/PredicatePushIntoScanChecker.java    |  1 +
 3 files changed, 62 insertions(+), 8 deletions(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBPredicateConversionTreeIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBPredicateConversionTreeIT.java
index afe09efb481..ba09872897b 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBPredicateConversionTreeIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBPredicateConversionTreeIT.java
@@ -34,6 +34,9 @@ import java.sql.Connection;
 import java.sql.Statement;
 
 import static org.apache.iotdb.db.it.utils.TestUtils.resultSetEqualTest;
+import static org.apache.iotdb.itbase.constant.TestConstant.DEVICE;
+import static org.apache.iotdb.itbase.constant.TestConstant.TIMESTAMP_STR;
+import static org.apache.iotdb.itbase.constant.TestConstant.count;
 import static org.junit.Assert.fail;
 
 @RunWith(IoTDBTestRunner.class)
@@ -290,4 +293,51 @@ public class IoTDBPredicateConversionTreeIT {
         expectedHeaderInt64,
         allInt64Rows);
   }
+
+  @Test
+  public void testWhereAndHavingWithNot() {
+    // Non align by device: WHERE with NOT
+    String[] expectedWhereHeader = new String[] {TIMESTAMP_STR, DEVICE_ID + 
".int32_col"};
+    String[] whereRetArray = new String[] {"1,20,", "8,1000,", "9,-29,", 
"10,-30,"};
+    resultSetEqualTest(
+        "SELECT int32_col FROM " + DEVICE_ID + " WHERE NOT (int32_col > 20 AND 
int32_col < 40)",
+        expectedWhereHeader,
+        whereRetArray);
+
+    // Non align by device: HAVING with NOT
+    String[] expectedHavingHeader = new String[] {TIMESTAMP_STR, 
count(DEVICE_ID + ".int32_col")};
+    String[] havingRetArray = new String[] {"5,1,", "7,1,"};
+    resultSetEqualTest(
+        "SELECT count(int32_col) FROM "
+            + DEVICE_ID
+            + " GROUP BY ([1,11),2ms) HAVING NOT (count(int32_col) > 1)",
+        expectedHavingHeader,
+        havingRetArray);
+
+    // Align by device: WHERE with NOT
+    String[] expectedWhereAlignByDeviceHeader = new String[] {TIMESTAMP_STR, 
DEVICE, "int32_col"};
+    String[] whereAlignByDeviceRetArray =
+        new String[] {
+          "1,root.test_pred.d1,20,",
+          "8,root.test_pred.d1,1000,",
+          "9,root.test_pred.d1,-29,",
+          "10,root.test_pred.d1,-30,",
+        };
+    resultSetEqualTest(
+        "SELECT int32_col FROM root.test_pred.* WHERE NOT (int32_col > 20 AND 
int32_col < 40) ALIGN BY DEVICE",
+        expectedWhereAlignByDeviceHeader,
+        whereAlignByDeviceRetArray);
+
+    // Align by device: HAVING with NOT
+    String[] expectedHavingAlignByDeviceHeader =
+        new String[] {TIMESTAMP_STR, DEVICE, count("int32_col")};
+    String[] havingAlignByDeviceRetArray =
+        new String[] {
+          "5,root.test_pred.d1,1,", "7,root.test_pred.d1,1,",
+        };
+    resultSetEqualTest(
+        "SELECT count(int32_col) FROM root.test_pred.* GROUP BY ([1,11),2ms) 
HAVING NOT (count(int32_col) > 1) ALIGN BY DEVICE",
+        expectedHavingAlignByDeviceHeader,
+        havingAlignByDeviceRetArray);
+  }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
index 7aa8d1e8636..fd8780f5d68 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
@@ -983,10 +983,12 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
       ISchemaTree schemaTree,
       UnaryOperator<Expression> havingExpressionAnalyzer,
       MPPQueryContext queryContext) {
+    Expression havingPredicate =
+        
PredicateUtils.predicateRemoveNot(queryStatement.getHavingCondition().getPredicate());
     // get removeWildcard Expressions in Having
     List<Expression> conJunctions =
         ExpressionAnalyzer.bindSchemaForPredicate(
-            queryStatement.getHavingCondition().getPredicate(),
+            havingPredicate,
             queryStatement.getFromComponent().getPrefixPaths(),
             schemaTree,
             true,
@@ -1062,7 +1064,8 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
     Map<IDeviceID, Set<Expression>> deviceToOutputExpressions =
         analysis.getDeviceToOutputExpressions();
 
-    Expression havingExpression = 
queryStatement.getHavingCondition().getPredicate();
+    Expression havingExpression =
+        
PredicateUtils.predicateRemoveNot(queryStatement.getHavingCondition().getPredicate());
     Set<Expression> conJunctions = new HashSet<>();
 
     for (PartialPath device : deviceSet) {
@@ -1522,9 +1525,11 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
     if (!queryStatement.hasWhere()) {
       return;
     }
+    Expression wherePredicate =
+        
PredicateUtils.predicateRemoveNot(queryStatement.getWhereCondition().getPredicate());
     List<Expression> conJunctions =
         ExpressionAnalyzer.bindSchemaForPredicate(
-            queryStatement.getWhereCondition().getPredicate(),
+            wherePredicate,
             queryStatement.getFromComponent().getPrefixPaths(),
             schemaTree,
             true,
@@ -1548,13 +1553,11 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
       final PartialPath devicePath,
       final ISchemaTree schemaTree,
       final MPPQueryContext queryContext) {
+    Expression wherePredicate =
+        
PredicateUtils.predicateRemoveNot(queryStatement.getWhereCondition().getPredicate());
     List<Expression> conJunctions =
         ExpressionAnalyzer.concatDeviceAndBindSchemaForPredicate(
-            queryStatement.getWhereCondition().getPredicate(),
-            devicePath,
-            schemaTree,
-            true,
-            queryContext);
+            wherePredicate, devicePath, schemaTree, true, queryContext);
     return convertConJunctionsToWhereExpression(conJunctions);
   }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/predicate/PredicatePushIntoScanChecker.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/predicate/PredicatePushIntoScanChecker.java
index 31ae325b328..63e9c7f7889 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/predicate/PredicatePushIntoScanChecker.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/predicate/PredicatePushIntoScanChecker.java
@@ -89,6 +89,7 @@ public class PredicatePushIntoScanChecker extends 
PredicateVisitor<Boolean, Void
 
   @Override
   public Boolean visitLogicNotExpression(LogicNotExpression 
logicNotExpression, Void context) {
+    // Not should have been removed in analyze stage
     throw new IllegalArgumentException(CONTAIN_NOT_ERR_MSG);
   }
 

Reply via email to