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

morrysnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 1212b65045f [fix](Nereids) Fix ClassCastException when HAVING clause 
contains subquery (#58978)
1212b65045f is described below

commit 1212b65045f570d95e8feb4ba355464afdfb6885
Author: lw112 <[email protected]>
AuthorDate: Fri Jan 16 15:33:31 2026 +0800

    [fix](Nereids) Fix ClassCastException when HAVING clause contains subquery 
(#58978)
    
    Issue Number: #58937
    Related PR: #46401
---
 .../trees/plans/logical/LogicalAggregate.java      | 30 +++++++++---
 .../plans/physical/PhysicalHashAggregate.java      | 30 +++++++++---
 .../test_having_subquery_with_nullliteral.out      |  5 ++
 .../test_having_subquery_with_nullliteral.groovy   | 54 ++++++++++++++++++++++
 4 files changed, 107 insertions(+), 12 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalAggregate.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalAggregate.java
index 9499dc601ca..d063ccb40aa 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalAggregate.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalAggregate.java
@@ -424,9 +424,18 @@ public class LogicalAggregate<CHILD_TYPE extends Plan>
             return;
         }
         DataTrait childFd = child(0).getLogicalProperties().getTrait();
-        ImmutableSet<Slot> groupByKeys = groupByExpressions.stream()
-                .map(s -> (Slot) s)
-                .collect(ImmutableSet.toImmutableSet());
+
+        if 
(groupByExpressions.stream().anyMatch(Expression::containsUniqueFunction)) {
+            return;
+        }
+
+        // Extract all input slots from group by expressions
+        ImmutableSet.Builder<Slot> groupByKeysBuilder = ImmutableSet.builder();
+        for (Expression expr : groupByExpressions) {
+            groupByKeysBuilder.addAll(expr.getInputSlots());
+        }
+        ImmutableSet<Slot> groupByKeys = groupByKeysBuilder.build();
+
         // when group by all tuples, the result only have one row
         if (groupByExpressions.isEmpty() || 
childFd.isUniformAndNotNull(groupByKeys)) {
             getOutput().forEach(builder::addUniqueSlot);
@@ -459,9 +468,18 @@ public class LogicalAggregate<CHILD_TYPE extends Plan>
             // roll up may generate new data
             return;
         }
-        ImmutableSet<Slot> groupByKeys = groupByExpressions.stream()
-                .map(s -> (Slot) s)
-                .collect(ImmutableSet.toImmutableSet());
+
+        if 
(groupByExpressions.stream().anyMatch(Expression::containsUniqueFunction)) {
+            return;
+        }
+
+        // Extract all input slots from group by expressions
+        ImmutableSet.Builder<Slot> groupByKeysBuilder = ImmutableSet.builder();
+        for (Expression expr : groupByExpressions) {
+            groupByKeysBuilder.addAll(expr.getInputSlots());
+        }
+        ImmutableSet<Slot> groupByKeys = groupByKeysBuilder.build();
+
         // when group by all tuples, the result only have one row
         if (groupByExpressions.isEmpty() || 
childFd.isUniformAndNotNull(groupByKeys)) {
             getOutput().forEach(builder::addUniformSlot);
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalHashAggregate.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalHashAggregate.java
index 95509540c43..3a53381e3bb 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalHashAggregate.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalHashAggregate.java
@@ -403,9 +403,18 @@ public class PhysicalHashAggregate<CHILD_TYPE extends 
Plan> extends PhysicalUnar
     @Override
     public void computeUnique(DataTrait.Builder builder) {
         DataTrait childFd = child(0).getLogicalProperties().getTrait();
-        ImmutableSet<Slot> groupByKeys = groupByExpressions.stream()
-                .map(s -> (Slot) s)
-                .collect(ImmutableSet.toImmutableSet());
+
+        if 
(groupByExpressions.stream().anyMatch(Expression::containsUniqueFunction)) {
+            return;
+        }
+
+        // Extract all input slots from group by expressions
+        ImmutableSet.Builder<Slot> groupByKeysBuilder = ImmutableSet.builder();
+        for (Expression expr : groupByExpressions) {
+            groupByKeysBuilder.addAll(expr.getInputSlots());
+        }
+        ImmutableSet<Slot> groupByKeys = groupByKeysBuilder.build();
+
         // when group by all tuples, the result only have one row
         if (groupByExpressions.isEmpty() || 
childFd.isUniformAndNotNull(groupByKeys)) {
             getOutput().forEach(builder::addUniqueSlot);
@@ -433,9 +442,18 @@ public class PhysicalHashAggregate<CHILD_TYPE extends 
Plan> extends PhysicalUnar
         // always propagate uniform
         DataTrait childFd = child(0).getLogicalProperties().getTrait();
         builder.addUniformSlot(childFd);
-        ImmutableSet<Slot> groupByKeys = groupByExpressions.stream()
-                .map(s -> (Slot) s)
-                .collect(ImmutableSet.toImmutableSet());
+
+        if 
(groupByExpressions.stream().anyMatch(Expression::containsUniqueFunction)) {
+            return;
+        }
+
+        // Extract all input slots from group by expressions
+        ImmutableSet.Builder<Slot> groupByKeysBuilder = ImmutableSet.builder();
+        for (Expression expr : groupByExpressions) {
+            groupByKeysBuilder.addAll(expr.getInputSlots());
+        }
+        ImmutableSet<Slot> groupByKeys = groupByKeysBuilder.build();
+
         // when group by all tuples, the result only have one row
         if (groupByExpressions.isEmpty() || 
childFd.isUniformAndNotNull(groupByKeys)) {
             getOutput().forEach(builder::addUniformSlot);
diff --git 
a/regression-test/data/correctness_p0/test_having_subquery_with_nullliteral.out 
b/regression-test/data/correctness_p0/test_having_subquery_with_nullliteral.out
new file mode 100644
index 00000000000..255c377c0e9
--- /dev/null
+++ 
b/regression-test/data/correctness_p0/test_having_subquery_with_nullliteral.out
@@ -0,0 +1,5 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !having_count_distinct_subquery --
+202501
+202502
+
diff --git 
a/regression-test/suites/correctness_p0/test_having_subquery_with_nullliteral.groovy
 
b/regression-test/suites/correctness_p0/test_having_subquery_with_nullliteral.groovy
new file mode 100644
index 00000000000..4e65dfd09d1
--- /dev/null
+++ 
b/regression-test/suites/correctness_p0/test_having_subquery_with_nullliteral.groovy
@@ -0,0 +1,54 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+suite("test_having_subquery_with_nullliteral") {
+    sql "SET enable_nereids_planner=true"
+    sql "SET enable_fallback_to_original_planner=false"
+
+    sql "drop table if exists test_having_subquery"
+
+    sql """
+    CREATE TABLE test_having_subquery (
+            id INT NOT NULL,
+            name VARCHAR(25) NOT NULL,
+            time VARCHAR(40) NOT NULL
+        ) ENGINE=OLAP
+        DUPLICATE KEY(id)
+        DISTRIBUTED BY HASH(id) BUCKETS 1
+        PROPERTIES (
+            "replication_num" = "1"
+        )
+    """
+
+    sql "INSERT INTO test_having_subquery VALUES(1,'jack','202501')"
+    sql "INSERT INTO test_having_subquery VALUES(2,'rose','202501')"
+    sql "INSERT INTO test_having_subquery VALUES(3,'tom','202502')"
+
+    qt_having_count_distinct_subquery """
+    SELECT time
+        FROM test_having_subquery
+        GROUP BY time
+        HAVING COUNT(DISTINCT time) = (
+            SELECT COUNT(DISTINCT time)
+            FROM test_having_subquery
+            WHERE time IN ('202501')
+        )
+        ORDER BY time
+    """
+
+    sql "drop table if exists test_having_subquery"
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to