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

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

commit c9e7a7771b731add7ef98501d33f5b8c49f53931
Author: Weihao Li <[email protected]>
AuthorDate: Wed May 27 09:48:36 2026 +0800

    fix
    
    Signed-off-by: Weihao Li <[email protected]>
---
 .../it/query/IoTDBPredicateConversionTreeIT.java   | 50 ++++++++++++++++++++++
 .../queryengine/plan/analyze/AnalyzeVisitor.java   |  3 ++
 .../predicate/PredicatePushIntoScanChecker.java    |  4 +-
 3 files changed, 54 insertions(+), 3 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..b58771c4148 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
@@ -994,6 +994,7 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
     Expression havingExpression =
         PredicateUtils.combineConjuncts(
             conJunctions.stream().distinct().collect(Collectors.toList()));
+    havingExpression = PredicateUtils.predicateRemoveNot(havingExpression);
     havingExpression = havingExpressionAnalyzer.apply(havingExpression);
 
     TSDataType outputType = analyzeExpressionType(analysis, havingExpression);
@@ -1100,6 +1101,7 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
     }
 
     havingExpression = PredicateUtils.combineConjuncts(new 
ArrayList<>(conJunctions));
+    havingExpression = PredicateUtils.predicateRemoveNot(havingExpression);
     TSDataType outputType = analyzeExpressionType(analysis, havingExpression);
     if (outputType != TSDataType.BOOLEAN) {
       throw new SemanticException(
@@ -1562,6 +1564,7 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
     Expression predicate =
         PredicateUtils.combineConjuncts(
             conJunctions.stream().distinct().collect(Collectors.toList()));
+    predicate = PredicateUtils.predicateRemoveNot(predicate);
     predicate = PredicateUtils.simplifyPredicate(predicate);
     predicate = normalizeExpression(predicate);
     return predicate;
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..7cd01314a89 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
@@ -39,8 +39,6 @@ import 
org.apache.iotdb.db.queryengine.plan.expression.unary.LikeExpression;
 import 
org.apache.iotdb.db.queryengine.plan.expression.unary.LogicNotExpression;
 import org.apache.iotdb.db.queryengine.plan.expression.unary.RegularExpression;
 
-import static org.apache.tsfile.read.filter.operator.Not.CONTAIN_NOT_ERR_MSG;
-
 public class PredicatePushIntoScanChecker extends PredicateVisitor<Boolean, 
Void> {
 
   @Override
@@ -89,7 +87,7 @@ public class PredicatePushIntoScanChecker extends 
PredicateVisitor<Boolean, Void
 
   @Override
   public Boolean visitLogicNotExpression(LogicNotExpression 
logicNotExpression, Void context) {
-    throw new IllegalArgumentException(CONTAIN_NOT_ERR_MSG);
+    return Boolean.FALSE;
   }
 
   @Override

Reply via email to