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 19a6089e4f9 [fix](rbo) Respect aggregate null-row semantics in CASE 
rewrite (#67818)
19a6089e4f9 is described below

commit 19a6089e4f95684ca05c3826eeb92d1c5bb1ec25
Author: morrySnow <[email protected]>
AuthorDate: Mon Sep 14 17:51:42 2026 +0800

    [fix](rbo) Respect aggregate null-row semantics in CASE rewrite (#67818)
    
    ### What problem does this PR solve?
    
    #### Problem
    
    `agg(CASE WHEN predicate THEN value END)` cannot always be replaced by
    `agg(value)` over `FILTER predicate`. Aggregates such as `array_agg`
    preserve a
    NULL element for an unmatched row, so filtering that row changes the
    result.
    
    #### Root cause
    
    The CASE rewrite did not require a semantic guarantee that the aggregate
    ignores a complete input row whenever any aggregate argument is SQL
    NULL. The
    same guarantee is also consumed when inferring not-null predicates below
    a
    global aggregate, but it was not represented as an explicit class-wide
    contract.
    
    #### Reproduction
    
    For an input containing one matching row and one non-matching row,
    `array_size(array_agg(CASE WHEN predicate THEN value END))` is `2`: one
    value
    and one NULL element. The old rewrite filtered the non-matching row and
    returned
    `1`.
    
    #### Fix
    
    - Gate CASE simplification on an explicit null-row semantic marker.
    - Define the marker as invariance under adding or removing any row in
    which at
    least one aggregate argument is NULL. Consequently, an input consisting
    only
    of such rows must produce the same result as empty input; this is
    independent
      of whether the result type itself is nullable.
    - Audit every marked built-in across all signatures and modes. Generic
    unary,
    multi-argument, and variadic backend wrappers skip a row before nested
    `add`
    when any nullable argument is NULL. Manually constructed implementations
    are
      marked only when their `add` path has the same behavior.
    - Verify multi-argument configuration paths including the TopN family,
      two-argument `collect_list`, `intersect_count`, sequence functions,
    window-funnel functions, and `retention`; their complete argument lists
    pass
      through the nullable wrapper.
    - Verify DISTINCT paths. The distinct combinator is itself wrapped using
    the
    original nullable argument types, so NULL tuples are skipped before
    entering
      the distinct set. Multi-phase DISTINCT retains the same invariant.
    - Leave known NULL-preserving functions `ArrayAgg`, `MapAgg`, and
    `MapAggV2`
    unmarked. Leave `CountByEnum` unmarked because it has different NULL
    handling.
    Leave `GroupConcat` and `MultiDistinctGroupConcat` unmarked because
    their
      class-wide ORDER BY signatures are not proven by the ordinary argument
      wrapper contract.
    
    #### Tests
    
    - `CUSTOM_MVN=/usr/local/bin/mvn ./run-fe-ut.sh --run
    org.apache.doris.nereids.rules.rewrite.InferAggNotNullTest`
      - 11 tests, 0 failures, 0 errors
    - `CUSTOM_MVN=/usr/local/bin/mvn DISABLE_BUILD_UI=ON ./build.sh --fe`
      - full FE build and Checkstyle succeeded
    - `infer_agg_not_null`
      - force-generated output and normal run succeeded
    - `eliminate_aggregate_casewhen`
      - force-generated output and normal run succeeded
    - covers safe nullable and not-nullable identities, unsafe
    NULL-preserving
        functions, and positive/negative DISTINCT behavior
    
    ### Release note
    
    Fix incorrect results when simplifying CASE expressions inside
    NULL-preserving
    aggregate functions.
---
 .../rules/rewrite/EliminateAggCaseWhen.java        |  4 ++
 .../trees/expressions/functions/agg/AIAgg.java     |  2 +-
 .../trees/expressions/functions/agg/AnyValue.java  |  3 +-
 .../expressions/functions/agg/AvgWeighted.java     |  2 +-
 .../trees/expressions/functions/agg/BitmapAgg.java |  2 +-
 .../expressions/functions/agg/BitmapIntersect.java |  3 +-
 .../expressions/functions/agg/BitmapUnion.java     |  3 +-
 .../functions/agg/BitmapUnionCount.java            |  3 +-
 .../expressions/functions/agg/BitmapUnionInt.java  |  2 +-
 .../trees/expressions/functions/agg/BoolAnd.java   |  2 +-
 .../trees/expressions/functions/agg/BoolOr.java    |  2 +-
 .../trees/expressions/functions/agg/BoolXor.java   |  2 +-
 .../expressions/functions/agg/CollectList.java     |  2 +-
 .../expressions/functions/agg/CollectSet.java      |  2 +-
 .../trees/expressions/functions/agg/Corr.java      |  2 +-
 .../expressions/functions/agg/CorrWelford.java     |  2 +-
 .../trees/expressions/functions/agg/Covar.java     |  2 +-
 .../trees/expressions/functions/agg/CovarSamp.java |  2 +-
 .../functions/agg/DataSketchesHllUnionAgg.java     |  3 +-
 .../functions/agg/ExponentialMovingAverage.java    |  2 +-
 .../functions/agg/GroupArrayIntersect.java         |  2 +-
 .../expressions/functions/agg/GroupArrayUnion.java |  2 +-
 .../expressions/functions/agg/GroupBitAnd.java     |  2 +-
 .../expressions/functions/agg/GroupBitOr.java      |  2 +-
 .../expressions/functions/agg/GroupBitXor.java     |  2 +-
 .../expressions/functions/agg/GroupBitmapXor.java  |  2 +-
 .../trees/expressions/functions/agg/Histogram.java |  2 +-
 .../trees/expressions/functions/agg/HllUnion.java  |  3 +-
 .../expressions/functions/agg/HllUnionAgg.java     |  3 +-
 .../expressions/functions/agg/IntersectCount.java  |  2 +-
 .../trees/expressions/functions/agg/Kurt.java      |  3 +-
 .../expressions/functions/agg/LinearHistogram.java |  3 +-
 .../functions/agg/MapAggregateFunction.java        |  2 +-
 .../trees/expressions/functions/agg/MaxBy.java     |  2 +-
 .../trees/expressions/functions/agg/Median.java    |  2 +-
 .../trees/expressions/functions/agg/MinBy.java     |  2 +-
 .../functions/agg/MultiDistinctCount.java          |  2 +-
 .../functions/agg/MultiDistinctSum.java            |  3 +-
 .../functions/agg/MultiDistinctSum0.java           |  3 +-
 .../trees/expressions/functions/agg/Ndv.java       |  3 +-
 .../agg/NullIgnoringAggregateFunction.java         |  8 ++-
 .../agg/OrthogonalBitmapExprCalculate.java         |  3 +-
 .../agg/OrthogonalBitmapExprCalculateCount.java    |  3 +-
 .../functions/agg/OrthogonalBitmapIntersect.java   |  2 +-
 .../agg/OrthogonalBitmapIntersectCount.java        |  2 +-
 .../functions/agg/OrthogonalBitmapUnionCount.java  |  3 +-
 .../expressions/functions/agg/Percentile.java      |  2 +-
 .../functions/agg/PercentileApprox.java            |  2 +-
 .../functions/agg/PercentileApproxArray.java       |  2 +-
 .../functions/agg/PercentileApproxWeighted.java    |  2 +-
 .../expressions/functions/agg/PercentileArray.java |  2 +-
 .../functions/agg/PercentileReservoir.java         |  2 +-
 .../expressions/functions/agg/QuantileUnion.java   |  2 +-
 .../trees/expressions/functions/agg/RegrAvgx.java  |  3 +-
 .../trees/expressions/functions/agg/RegrAvgy.java  |  3 +-
 .../trees/expressions/functions/agg/RegrCount.java |  2 +-
 .../expressions/functions/agg/RegrIntercept.java   |  3 +-
 .../trees/expressions/functions/agg/RegrR2.java    |  3 +-
 .../trees/expressions/functions/agg/RegrSlope.java |  3 +-
 .../trees/expressions/functions/agg/RegrSxx.java   |  3 +-
 .../trees/expressions/functions/agg/RegrSxy.java   |  3 +-
 .../trees/expressions/functions/agg/RegrSyy.java   |  3 +-
 .../trees/expressions/functions/agg/Retention.java |  2 +-
 .../trees/expressions/functions/agg/Sem.java       |  2 +-
 .../expressions/functions/agg/SequenceCount.java   |  2 +-
 .../expressions/functions/agg/SequenceMatch.java   |  2 +-
 .../trees/expressions/functions/agg/Skew.java      |  3 +-
 .../trees/expressions/functions/agg/Stddev.java    |  2 +-
 .../expressions/functions/agg/StddevSamp.java      |  2 +-
 .../trees/expressions/functions/agg/Sum0.java      |  3 +-
 .../trees/expressions/functions/agg/TopN.java      |  2 +-
 .../trees/expressions/functions/agg/TopNArray.java |  2 +-
 .../expressions/functions/agg/TopNWeighted.java    |  2 +-
 .../trees/expressions/functions/agg/Variance.java  |  2 +-
 .../expressions/functions/agg/VarianceSamp.java    |  2 +-
 .../expressions/functions/agg/WindowFunnel.java    |  2 +-
 .../expressions/functions/agg/WindowFunnelV2.java  |  2 +-
 .../nereids/rules/rewrite/InferAggNotNullTest.java | 34 ++++++++++
 .../eliminate_aggregate_casewhen.out               | 74 ++++++++++++++++++++++
 .../infer_agg_not_null/infer_agg_not_null.out      |  9 +++
 .../eliminate_aggregate_casewhen.groovy            | 50 +++++++++++++++
 .../infer_agg_not_null/infer_agg_not_null.groovy   | 47 ++++++++++++++
 82 files changed, 324 insertions(+), 77 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateAggCaseWhen.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateAggCaseWhen.java
index 33a9bbd9242..bd24c50f87d 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateAggCaseWhen.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateAggCaseWhen.java
@@ -21,6 +21,7 @@ import org.apache.doris.nereids.rules.Rule;
 import org.apache.doris.nereids.rules.RuleType;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import 
org.apache.doris.nereids.trees.expressions.functions.agg.AggregateFunction;
+import 
org.apache.doris.nereids.trees.expressions.functions.agg.NullIgnoringAggregateFunction;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.If;
 import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
 import org.apache.doris.nereids.trees.plans.Plan;
@@ -57,6 +58,9 @@ public final class EliminateAggCaseWhen extends 
OneRewriteRuleFactory {
                 return null;
             }
             for (AggregateFunction aggFun : aggFunctions) {
+                if (!(aggFun instanceof NullIgnoringAggregateFunction)) {
+                    return null;
+                }
                 // check whether we only have on case when/if in aggregate 
function
                 if (aggFun.getArguments().size() != 1) {
                     return null;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/AIAgg.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/AIAgg.java
index 4785718b9fa..5235b243d78 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/AIAgg.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/AIAgg.java
@@ -40,7 +40,7 @@ import java.util.List;
  * AggregateFunction 'AI_AGG'.
  */
 public class AIAgg extends NullableAggregateFunction
-        implements ExplicitlyCastableSignature, NotSupportAggState {
+        implements ExplicitlyCastableSignature, NotSupportAggState, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(StringType.INSTANCE).args(StringType.INSTANCE, 
StringType.INSTANCE),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/AnyValue.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/AnyValue.java
index 40f792c9569..016fb817c4a 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/AnyValue.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/AnyValue.java
@@ -34,7 +34,8 @@ import java.util.List;
  * AggregateFunction 'any_value'. This class is generated by GenerateFunction.
  */
 public class AnyValue extends NullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature, RollUpTrait {
+        implements UnaryExpression, ExplicitlyCastableSignature, RollUpTrait,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.retArgType(0).args(AnyDataType.INSTANCE_WITHOUT_INDEX)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/AvgWeighted.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/AvgWeighted.java
index d57958cd056..adf16b7c493 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/AvgWeighted.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/AvgWeighted.java
@@ -33,7 +33,7 @@ import java.util.List;
  * AggregateFunction 'avg_weighted'. This class is generated by 
GenerateFunction.
  */
 public class AvgWeighted extends NullableAggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE, 
DoubleType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapAgg.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapAgg.java
index 7083e7f0fe7..2b3eaef9661 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapAgg.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapAgg.java
@@ -37,7 +37,7 @@ import java.util.List;
  * AggregateFunction 'bitmap_agg'.
  */
 public class BitmapAgg extends NotNullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(BitmapType.INSTANCE).args(BigIntType.INSTANCE),
             
FunctionSignature.ret(BitmapType.INSTANCE).args(IntegerType.INSTANCE),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapIntersect.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapIntersect.java
index 382b242123a..5865e638d4d 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapIntersect.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapIntersect.java
@@ -35,7 +35,8 @@ import java.util.List;
  * AggregateFunction 'bitmap_intersect'. This class is generated by 
GenerateFunction.
  */
 public class BitmapIntersect extends NotNullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature, 
BitmapFunction {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
BitmapFunction,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(BitmapType.INSTANCE).args(BitmapType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapUnion.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapUnion.java
index 01cecaff52b..1370889c32e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapUnion.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapUnion.java
@@ -36,7 +36,8 @@ import java.util.List;
  * AggregateFunction 'bitmap_union'. This class is generated by 
GenerateFunction.
  */
 public class BitmapUnion extends NotNullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature, 
BitmapFunction, RollUpTrait {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
BitmapFunction, RollUpTrait,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(BitmapType.INSTANCE).args(BitmapType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapUnionCount.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapUnionCount.java
index 185af63fac4..2be34c5f4e7 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapUnionCount.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapUnionCount.java
@@ -37,7 +37,8 @@ import java.util.List;
  * AggregateFunction 'bitmap_union_count'. This class is generated by 
GenerateFunction.
  */
 public class BitmapUnionCount extends NotNullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature, 
BitmapFunction, RollUpTrait {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
BitmapFunction, RollUpTrait,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(BigIntType.INSTANCE).args(BitmapType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapUnionInt.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapUnionInt.java
index 9ce84a0f084..8de87e71bc2 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapUnionInt.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BitmapUnionInt.java
@@ -41,7 +41,7 @@ import java.util.List;
  * AggregateFunction 'bitmap_union_int'. This class is generated by 
GenerateFunction.
  */
 public class BitmapUnionInt extends NotNullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(BigIntType.INSTANCE).args(SmallIntType.INSTANCE),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BoolAnd.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BoolAnd.java
index 02f8dbec79a..4569144ce28 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BoolAnd.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BoolAnd.java
@@ -35,7 +35,7 @@ import java.util.List;
  * AggregateFunction 'bool_and'.
  */
 public class BoolAnd extends NullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(BooleanType.INSTANCE).args(BooleanType.INSTANCE)
     );
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BoolOr.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BoolOr.java
index 3eefb907d68..e81d9a460cd 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BoolOr.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BoolOr.java
@@ -35,7 +35,7 @@ import java.util.List;
  * AggregateFunction 'bool_or'.
  */
 public class BoolOr extends NullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(BooleanType.INSTANCE).args(BooleanType.INSTANCE)
     );
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BoolXor.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BoolXor.java
index 6e84899ec91..471fe3a33de 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BoolXor.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/BoolXor.java
@@ -35,7 +35,7 @@ import java.util.List;
  * AggregateFunction 'bool_xor'.
  */
 public class BoolXor extends NullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(BooleanType.INSTANCE).args(BooleanType.INSTANCE)
     );
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CollectList.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CollectList.java
index 6c447a22b6d..6d2f715230f 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CollectList.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CollectList.java
@@ -39,7 +39,7 @@ import java.util.List;
  * AggregateFunction 'collect_list'. This class is generated by 
GenerateFunction.
  */
 public class CollectList extends NotNullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             FunctionSignature.ret(ArrayType.of(new 
FollowToAnyDataType(0))).args(new AnyDataType(0)),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CollectSet.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CollectSet.java
index 66f17dd5c16..e252ab4368e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CollectSet.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CollectSet.java
@@ -38,7 +38,7 @@ import java.util.List;
  * AggregateFunction 'collect_set'. This class is generated by 
GenerateFunction.
  */
 public class CollectSet extends NotNullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             FunctionSignature.ret(ArrayType.of(new 
FollowToAnyDataType(0))).args(new AnyDataType(0)),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Corr.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Corr.java
index 5d9f9ac5f23..68b06a35e79 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Corr.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Corr.java
@@ -33,7 +33,7 @@ import java.util.List;
  * AggregateFunction 'corr'. This class is generated by GenerateFunction.
  */
 public class Corr extends NullableAggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE, 
DoubleType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CorrWelford.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CorrWelford.java
index b0d51f1a26b..bd36cc4de08 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CorrWelford.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CorrWelford.java
@@ -33,7 +33,7 @@ import java.util.List;
  * AggregateFunction 'corr_welford'. This class is generated by 
GenerateFunction.
  */
 public class CorrWelford extends NullableAggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE, 
DoubleType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Covar.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Covar.java
index 2043ce716d1..6f63538b428 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Covar.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Covar.java
@@ -33,7 +33,7 @@ import java.util.List;
  * AggregateFunction 'covar'. This class is generated by GenerateFunction.
  */
 public class Covar extends NullableAggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE, 
DoubleType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CovarSamp.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CovarSamp.java
index 5f100b6460f..e5adeec8f23 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CovarSamp.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CovarSamp.java
@@ -33,7 +33,7 @@ import java.util.List;
  * AggregateFunction 'covar_samp'. This class is generated by GenerateFunction.
  */
 public class CovarSamp extends NullableAggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE, 
DoubleType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/DataSketchesHllUnionAgg.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/DataSketchesHllUnionAgg.java
index 9fe46d2a77d..5091c45ca19 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/DataSketchesHllUnionAgg.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/DataSketchesHllUnionAgg.java
@@ -39,7 +39,8 @@ import java.util.List;
 
 /** datasketches_hll_union_agg agg function. */
 public class DataSketchesHllUnionAgg extends NotNullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature, 
FunctionTrait, RollUpTrait {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
FunctionTrait, RollUpTrait,
+        NullIgnoringAggregateFunction {
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(StringType.INSTANCE),
             
FunctionSignature.ret(DoubleType.INSTANCE).args(VarcharType.SYSTEM_DEFAULT),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/ExponentialMovingAverage.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/ExponentialMovingAverage.java
index 7ceda4cf912..03966416c36 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/ExponentialMovingAverage.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/ExponentialMovingAverage.java
@@ -43,7 +43,7 @@ import java.util.List;
  * timestamp columns use {@code intDiv(toUnixTimestamp(ts), interval_seconds)}.
  */
 public class ExponentialMovingAverage extends NullableAggregateFunction
-        implements ExplicitlyCastableSignature {
+        implements ExplicitlyCastableSignature, NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             FunctionSignature.ret(DoubleType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupArrayIntersect.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupArrayIntersect.java
index ea0ea216fc9..aa0f87ae3e2 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupArrayIntersect.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupArrayIntersect.java
@@ -36,7 +36,7 @@ import java.util.List;
  * AggregateFunction 'group_array_intersect'.
  */
 public class GroupArrayIntersect extends NotNullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             FunctionSignature.retArgType(0)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupArrayUnion.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupArrayUnion.java
index a760b18ef37..5d4efdd2733 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupArrayUnion.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupArrayUnion.java
@@ -36,7 +36,7 @@ import java.util.List;
  * AggregateFunction 'group_array_union'.
  */
 public class GroupArrayUnion extends NotNullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             FunctionSignature.retArgType(0)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitAnd.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitAnd.java
index f85f9cef42c..7f7e119b1d6 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitAnd.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitAnd.java
@@ -37,7 +37,7 @@ import java.util.List;
  * AggregateFunction 'group_bit_and'. This class is generated by 
GenerateFunction.
  */
 public class GroupBitAnd extends NullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(LargeIntType.INSTANCE).args(LargeIntType.INSTANCE),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitOr.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitOr.java
index 86463f004f9..9e8006d32f3 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitOr.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitOr.java
@@ -38,7 +38,7 @@ import java.util.List;
  * AggregateFunction 'group_bit_or'. This class is generated by 
GenerateFunction.
  */
 public class GroupBitOr extends NullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(LargeIntType.INSTANCE).args(LargeIntType.INSTANCE),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitXor.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitXor.java
index aca1fca059f..b81c9b6ea4b 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitXor.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitXor.java
@@ -38,7 +38,7 @@ import java.util.List;
  * AggregateFunction 'group_bit_xor'. This class is generated by 
GenerateFunction.
  */
 public class GroupBitXor extends NullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(LargeIntType.INSTANCE).args(LargeIntType.INSTANCE),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitmapXor.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitmapXor.java
index f276f935048..bffa3a54c85 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitmapXor.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitmapXor.java
@@ -35,7 +35,7 @@ import java.util.List;
  * AggregateFunction 'group_bitmap_xor'. This class is generated by 
GenerateFunction.
  */
 public class GroupBitmapXor extends NullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(BitmapType.INSTANCE).args(BitmapType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Histogram.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Histogram.java
index 01486ff2bd6..d803552098f 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Histogram.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Histogram.java
@@ -37,7 +37,7 @@ import java.util.List;
  * AggregateFunction 'histogram'. This class is generated by GenerateFunction.
  */
 public class Histogram extends NotNullableAggregateFunction
-        implements ExplicitlyCastableSignature {
+        implements ExplicitlyCastableSignature, NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/HllUnion.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/HllUnion.java
index 37f1e206a4b..5eb0b3a5227 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/HllUnion.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/HllUnion.java
@@ -36,7 +36,8 @@ import java.util.List;
  * AggregateFunction 'hll_union'. This class is generated by GenerateFunction.
  */
 public class HllUnion extends NotNullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature, HllFunction, 
RollUpTrait {
+        implements UnaryExpression, ExplicitlyCastableSignature, HllFunction, 
RollUpTrait,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             FunctionSignature.ret(HllType.INSTANCE).args(HllType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/HllUnionAgg.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/HllUnionAgg.java
index ab37fa27927..ce516da455e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/HllUnionAgg.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/HllUnionAgg.java
@@ -37,7 +37,8 @@ import java.util.List;
  * AggregateFunction 'hll_union_agg'. This class is generated by 
GenerateFunction.
  */
 public class HllUnionAgg extends NotNullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature, HllFunction, 
RollUpTrait {
+        implements UnaryExpression, ExplicitlyCastableSignature, HllFunction, 
RollUpTrait,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             FunctionSignature.ret(BigIntType.INSTANCE).args(HllType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/IntersectCount.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/IntersectCount.java
index 5c178210e0f..994a173bb79 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/IntersectCount.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/IntersectCount.java
@@ -37,7 +37,7 @@ import java.util.List;
  * AggregateFunction 'intersect_count'. This class is generated by 
GenerateFunction.
  */
 public class IntersectCount extends NotNullableAggregateFunction
-        implements ExplicitlyCastableSignature, BitmapIntersectFunction {
+        implements ExplicitlyCastableSignature, BitmapIntersectFunction, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = 
DataType.trivialTypes().stream()
             .map(type -> 
FunctionSignature.ret(BigIntType.INSTANCE).varArgs(BitmapType.INSTANCE, type, 
type))
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Kurt.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Kurt.java
index d48cf37089c..4c48d53fd28 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Kurt.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Kurt.java
@@ -34,7 +34,8 @@ import java.util.List;
  * AggregateFunction 'Kurt'.
  */
 public class Kurt extends AggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/LinearHistogram.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/LinearHistogram.java
index f5e2893e4a3..ec7384bbfe2 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/LinearHistogram.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/LinearHistogram.java
@@ -35,7 +35,8 @@ import java.util.List;
 /**
  * AggregateFunction 'linear_histogram'.
  */
-public class LinearHistogram extends NotNullableAggregateFunction implements 
ExplicitlyCastableSignature {
+public class LinearHistogram extends NotNullableAggregateFunction
+        implements ExplicitlyCastableSignature, NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MapAggregateFunction.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MapAggregateFunction.java
index bc961b3d657..2722e47f690 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MapAggregateFunction.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MapAggregateFunction.java
@@ -32,7 +32,7 @@ import java.util.List;
 
 /** Base class for aggregate functions that aggregate Map values by key. */
 public abstract class MapAggregateFunction extends NotNullableAggregateFunction
-        implements UnaryExpression, CustomSignature {
+        implements UnaryExpression, CustomSignature, 
NullIgnoringAggregateFunction {
 
     protected MapAggregateFunction(String name, Expression arg) {
         this(name, false, arg);
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MaxBy.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MaxBy.java
index 63ca76c4800..96e6c040577 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MaxBy.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MaxBy.java
@@ -35,7 +35,7 @@ import java.util.List;
  * AggregateFunction 'max_by'. This class is generated by GenerateFunction.
  */
 public class MaxBy extends NullableAggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.retArgType(0).args(AnyDataType.INSTANCE_WITHOUT_INDEX, 
AnyDataType.INSTANCE_WITHOUT_INDEX)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Median.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Median.java
index f91af0352de..7c396c90bf4 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Median.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Median.java
@@ -41,7 +41,7 @@ import java.util.List;
  * AggregateFunction 'median'. This class is generated by GenerateFunction.
  */
 public class Median extends NullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MinBy.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MinBy.java
index ab3f7a68e74..b59c1a63062 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MinBy.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MinBy.java
@@ -35,7 +35,7 @@ import java.util.List;
  * AggregateFunction 'min_by'. This class is generated by GenerateFunction.
  */
 public class MinBy extends NullableAggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.retArgType(0).args(AnyDataType.INSTANCE_WITHOUT_INDEX, 
AnyDataType.INSTANCE_WITHOUT_INDEX)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MultiDistinctCount.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MultiDistinctCount.java
index 9e71a3eb647..fd4d23208cd 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MultiDistinctCount.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MultiDistinctCount.java
@@ -35,7 +35,7 @@ import java.util.List;
 
 /** MultiDistinctCount */
 public class MultiDistinctCount extends NotNullableAggregateFunction
-        implements ExplicitlyCastableSignature, MultiDistinction {
+        implements ExplicitlyCastableSignature, MultiDistinction, 
NullIgnoringAggregateFunction {
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(BigIntType.INSTANCE).varArgs(AnyDataType.INSTANCE_WITHOUT_INDEX)
     );
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MultiDistinctSum.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MultiDistinctSum.java
index 0e34ea50ba5..8d3f3500c6a 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MultiDistinctSum.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MultiDistinctSum.java
@@ -33,7 +33,8 @@ import java.util.List;
 
 /** MultiDistinctSum */
 public class MultiDistinctSum extends NullableAggregateFunction implements 
UnaryExpression,
-        ExplicitlyCastableSignature, ComputePrecisionForSum, MultiDistinction, 
NeedSessionVarGuard {
+        ExplicitlyCastableSignature, ComputePrecisionForSum, MultiDistinction, 
NeedSessionVarGuard,
+        NullIgnoringAggregateFunction {
     public MultiDistinctSum(Expression arg0) {
         this(false, arg0);
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MultiDistinctSum0.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MultiDistinctSum0.java
index f47adeac7d3..61e17bbf909 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MultiDistinctSum0.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MultiDistinctSum0.java
@@ -40,7 +40,8 @@ import java.util.List;
 
 /** MultiDistinctSum0 */
 public class MultiDistinctSum0 extends NotNullableAggregateFunction implements 
UnaryExpression,
-        ExplicitlyCastableSignature, ComputePrecisionForSum, MultiDistinction, 
NeedSessionVarGuard {
+        ExplicitlyCastableSignature, ComputePrecisionForSum, MultiDistinction, 
NeedSessionVarGuard,
+        NullIgnoringAggregateFunction {
     public MultiDistinctSum0(Expression arg0) {
         this(false, arg0);
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Ndv.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Ndv.java
index 760a702d27b..a10a1dd60b2 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Ndv.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Ndv.java
@@ -38,7 +38,8 @@ import java.util.List;
  * AggregateFunction 'ndv'. This class is generated by GenserateFunction.
  */
 public class Ndv extends NotNullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature, RollUpTrait {
+        implements UnaryExpression, ExplicitlyCastableSignature, RollUpTrait,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(BigIntType.INSTANCE).args(AnyDataType.INSTANCE_WITHOUT_INDEX)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/NullIgnoringAggregateFunction.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/NullIgnoringAggregateFunction.java
index 90b959b3ef7..6726922615c 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/NullIgnoringAggregateFunction.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/NullIgnoringAggregateFunction.java
@@ -21,8 +21,12 @@ package 
org.apache.doris.nereids.trees.expressions.functions.agg;
  * Marker for aggregate functions that ignore a row when any aggregate 
argument is SQL NULL.
  *
  * <p>Removing such rows does not change the aggregate result, so {@code 
InferAggNotNull} may add
- * inferred not-null predicates for their arguments. This describes input-row 
handling and is
- * independent of whether the aggregate result itself is nullable.
+ * inferred not-null predicates for their arguments. Equivalently, adding or 
removing rows with a
+ * NULL aggregate argument is result-invariant; in particular, an input 
consisting only of rows in
+ * which at least one aggregate argument is NULL must produce the same result 
as an empty input.
+ * This describes input-row handling and is independent of whether the 
aggregate result itself is
+ * nullable. A not-null result such as zero or an empty collection can 
therefore satisfy this
+ * contract.
  *
  * <p>Implement this interface only when the contract holds for every 
signature and mode of the
  * aggregate function, including DISTINCT.
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapExprCalculate.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapExprCalculate.java
index 6ddd211764d..eb17c454ee9 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapExprCalculate.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapExprCalculate.java
@@ -34,7 +34,8 @@ import java.util.List;
 
 /** OrthogonalBitmapExprCalculate */
 public class OrthogonalBitmapExprCalculate extends NotNullableAggregateFunction
-        implements OrthogonalBitmapFunction, ExplicitlyCastableSignature {
+        implements OrthogonalBitmapFunction, ExplicitlyCastableSignature,
+        NullIgnoringAggregateFunction {
 
     static final List<FunctionSignature> FUNCTION_SIGNATURES = 
ImmutableList.of(
             FunctionSignature.ret(BitmapType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapExprCalculateCount.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapExprCalculateCount.java
index 21b3232d4f7..f5f347f80d8 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapExprCalculateCount.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapExprCalculateCount.java
@@ -35,7 +35,8 @@ import java.util.List;
 
 /** OrthogonalBitmapExprCalculateCount */
 public class OrthogonalBitmapExprCalculateCount extends 
NotNullableAggregateFunction
-        implements OrthogonalBitmapFunction, ExplicitlyCastableSignature {
+        implements OrthogonalBitmapFunction, ExplicitlyCastableSignature,
+        NullIgnoringAggregateFunction {
 
     static final List<FunctionSignature> FUNCTION_SIGNATURES = 
ImmutableList.of(
             FunctionSignature.ret(BigIntType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapIntersect.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapIntersect.java
index 691f2866e77..6d1334f6418 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapIntersect.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapIntersect.java
@@ -34,7 +34,7 @@ import java.util.List;
  * AggregateFunction 'orthogonal_bitmap_intersect'. This class is generated by 
GenerateFunction.
  */
 public class OrthogonalBitmapIntersect extends NotNullableAggregateFunction
-        implements OrthogonalBitmapFunction, BitmapIntersectFunction {
+        implements OrthogonalBitmapFunction, BitmapIntersectFunction, 
NullIgnoringAggregateFunction {
 
     static final List<FunctionSignature> FUNCTION_SIGNATURES = 
SUPPORTED_TYPES.stream()
             .map(type -> 
FunctionSignature.ret(BitmapType.INSTANCE).varArgs(BitmapType.INSTANCE, type, 
type))
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapIntersectCount.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapIntersectCount.java
index 6f7793944b7..030c7faf20e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapIntersectCount.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapIntersectCount.java
@@ -31,7 +31,7 @@ import java.util.List;
  * AggregateFunction 'orthogonal_bitmap_intersect_count'. This class is 
generated by GenerateFunction.
  */
 public class OrthogonalBitmapIntersectCount extends 
NotNullableAggregateFunction
-        implements OrthogonalBitmapFunction, BitmapIntersectFunction {
+        implements OrthogonalBitmapFunction, BitmapIntersectFunction, 
NullIgnoringAggregateFunction {
 
     /**
      * constructor with 3 or more arguments.
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapUnionCount.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapUnionCount.java
index 4f6d9f12b7a..f1823c5de3a 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapUnionCount.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/OrthogonalBitmapUnionCount.java
@@ -35,7 +35,8 @@ import java.util.List;
  * AggregateFunction 'orthogonal_bitmap_union_count'. This class is generated 
by GenerateFunction.
  */
 public class OrthogonalBitmapUnionCount extends NotNullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature, 
NotSupportAggState {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
NotSupportAggState,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(BigIntType.INSTANCE).args(BitmapType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Percentile.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Percentile.java
index 16a2821a541..f1b7fc4d93c 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Percentile.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Percentile.java
@@ -40,7 +40,7 @@ import java.util.List;
  * AggregateFunction 'percentile'. This class is generated by GenerateFunction.
  */
 public class Percentile extends NullableAggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE, 
DoubleType.INSTANCE),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApprox.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApprox.java
index 3e0229a1234..a2234464f11 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApprox.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApprox.java
@@ -33,7 +33,7 @@ import java.util.List;
  * AggregateFunction 'percentile_approx'. This class is generated by 
GenerateFunction.
  */
 public class PercentileApprox extends NullableAggregateFunction
-        implements ExplicitlyCastableSignature {
+        implements ExplicitlyCastableSignature, NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE, 
DoubleType.INSTANCE),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApproxArray.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApproxArray.java
index 14010a401fe..72ffeb20594 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApproxArray.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApproxArray.java
@@ -38,7 +38,7 @@ import java.util.List;
  * AggregateFunction 'percentile_approx_array'.
  */
 public class PercentileApproxArray extends NotNullableAggregateFunction
-        implements ExplicitlyCastableSignature {
+        implements ExplicitlyCastableSignature, NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             FunctionSignature.ret(ArrayType.of(DoubleType.INSTANCE))
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApproxWeighted.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApproxWeighted.java
index 2eae91d865b..b0a58e84c96 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApproxWeighted.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApproxWeighted.java
@@ -33,7 +33,7 @@ import java.util.List;
  * AggregateFunction 'percentile_approx_weighted'.
  */
 public class PercentileApproxWeighted extends NullableAggregateFunction
-        implements ExplicitlyCastableSignature {
+        implements ExplicitlyCastableSignature, NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileArray.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileArray.java
index 89e8dded9a5..df892547db0 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileArray.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileArray.java
@@ -43,7 +43,7 @@ import java.util.List;
  * AggregateFunction 'percentile_array'. This class is generated by 
GenerateFunction.
  */
 public class PercentileArray extends NotNullableAggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             FunctionSignature.ret(ArrayType.of(DoubleType.INSTANCE))
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileReservoir.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileReservoir.java
index 5e91e794064..3e67f57b605 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileReservoir.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileReservoir.java
@@ -35,7 +35,7 @@ import java.util.List;
  * AggregateFunction 'percentile_reservoir'
  */
 public class PercentileReservoir extends NullableAggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE, 
DoubleType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/QuantileUnion.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/QuantileUnion.java
index 6b433e7895d..b6c533d2559 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/QuantileUnion.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/QuantileUnion.java
@@ -36,7 +36,7 @@ import java.util.List;
  * AggregateFunction 'quantile_union'. This class is generated by 
GenerateFunction.
  */
 public class QuantileUnion extends NotNullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(QuantileStateType.INSTANCE).args(QuantileStateType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrAvgx.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrAvgx.java
index c1f11c0321d..724bc60ff4d 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrAvgx.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrAvgx.java
@@ -32,7 +32,8 @@ import java.util.List;
 
 /** regr_avgx agg function. */
 public class RegrAvgx extends AggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE, 
DoubleType.INSTANCE));
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrAvgy.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrAvgy.java
index 1491cf71b81..5cdf2178e36 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrAvgy.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrAvgy.java
@@ -32,7 +32,8 @@ import java.util.List;
 
 /** regr_avgy agg function. */
 public class RegrAvgy extends AggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE, 
DoubleType.INSTANCE));
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrCount.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrCount.java
index fba0645428e..2c749b52e03 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrCount.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrCount.java
@@ -33,7 +33,7 @@ import java.util.List;
 
 /** regr_count agg function. */
 public class RegrCount extends NotNullableAggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(BigIntType.INSTANCE).args(DoubleType.INSTANCE, 
DoubleType.INSTANCE));
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrIntercept.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrIntercept.java
index 81afd0441b0..de508f038dc 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrIntercept.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrIntercept.java
@@ -34,7 +34,8 @@ import java.util.List;
  * AggregateFunction 'regr_intercept'.
  */
 public class RegrIntercept extends AggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE, 
DoubleType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrR2.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrR2.java
index 2ae74a8628c..e8d678ad3a6 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrR2.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrR2.java
@@ -32,7 +32,8 @@ import java.util.List;
 
 /** regr_r2 agg function. */
 public class RegrR2 extends AggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE, 
DoubleType.INSTANCE));
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrSlope.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrSlope.java
index fc964d317f7..4420c99bba7 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrSlope.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrSlope.java
@@ -34,7 +34,8 @@ import java.util.List;
  * AggregateFunction 'regr_slope'.
  */
 public class RegrSlope extends AggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE, 
DoubleType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrSxx.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrSxx.java
index 28f37781903..029a7275392 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrSxx.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrSxx.java
@@ -32,7 +32,8 @@ import java.util.List;
 
 /** regr_sxx agg function. */
 public class RegrSxx extends AggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE, 
DoubleType.INSTANCE));
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrSxy.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrSxy.java
index 39dd7dd2d84..2e3163af4fb 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrSxy.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrSxy.java
@@ -32,7 +32,8 @@ import java.util.List;
 
 /** regr_sxy agg function. */
 public class RegrSxy extends AggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE, 
DoubleType.INSTANCE));
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrSyy.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrSyy.java
index f1226818208..1ea117a2ad2 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrSyy.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/RegrSyy.java
@@ -32,7 +32,8 @@ import java.util.List;
 
 /** regr_syy agg function. */
 public class RegrSyy extends AggregateFunction
-        implements BinaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE, 
DoubleType.INSTANCE));
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Retention.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Retention.java
index 87177f34b38..ec6888b42fe 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Retention.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Retention.java
@@ -35,7 +35,7 @@ import java.util.List;
  * AggregateFunction 'retention'. This class is generated by GenerateFunction.
  */
 public class Retention extends NullableAggregateFunction
-        implements ExplicitlyCastableSignature {
+        implements ExplicitlyCastableSignature, NullIgnoringAggregateFunction {
 
     // The BE side stores the retention state in a fixed-size array
     // (RetentionState::MAX_EVENTS, uint8_t events[32]) and also serializes it 
into a single
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Sem.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Sem.java
index 7e0dbd53787..3f6be349fb1 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Sem.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Sem.java
@@ -34,7 +34,7 @@ import java.util.List;
  */
 
 public class Sem extends NullableAggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE));
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceCount.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceCount.java
index f0cc6fac537..813c63a9f34 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceCount.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceCount.java
@@ -40,7 +40,7 @@ import java.util.List;
  * AggregateFunction 'sequence_count'. This class is generated by 
GenerateFunction.
  */
 public class SequenceCount extends NotNullableAggregateFunction
-        implements ExplicitlyCastableSignature, SequenceFunction {
+        implements ExplicitlyCastableSignature, SequenceFunction, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             FunctionSignature.ret(BigIntType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceMatch.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceMatch.java
index 24dc7f8367a..87bd7925506 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceMatch.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceMatch.java
@@ -38,7 +38,7 @@ import java.util.List;
  * AggregateFunction 'sequence_match'. This class is generated by 
GenerateFunction.
  */
 public class SequenceMatch extends NullableAggregateFunction
-        implements ExplicitlyCastableSignature, SequenceFunction {
+        implements ExplicitlyCastableSignature, SequenceFunction, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             FunctionSignature.ret(BooleanType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Skew.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Skew.java
index aa46bcecc12..bba96f772a4 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Skew.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Skew.java
@@ -35,7 +35,8 @@ import java.util.List;
  */
 
 public class Skew extends AggregateFunction
-        implements UnaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable {
+        implements UnaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Stddev.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Stddev.java
index 1dd4e46f998..bfeecf10fa9 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Stddev.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Stddev.java
@@ -35,7 +35,7 @@ import java.util.List;
  */
 public class Stddev extends NullableAggregateFunction
         implements UnaryExpression, ExplicitlyCastableSignature,
-        StdDevOrVarianceFunction, DecimalStddevPrecision {
+        StdDevOrVarianceFunction, DecimalStddevPrecision, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE));
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/StddevSamp.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/StddevSamp.java
index 7eac03ca5c3..84e1359421a 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/StddevSamp.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/StddevSamp.java
@@ -35,7 +35,7 @@ import java.util.List;
  */
 public class StddevSamp extends NullableAggregateFunction
         implements UnaryExpression, ExplicitlyCastableSignature,
-        StdDevOrVarianceFunction, DecimalStddevPrecision {
+        StdDevOrVarianceFunction, DecimalStddevPrecision, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE));
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Sum0.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Sum0.java
index 2bf5f9e2fa3..5c19b826e3c 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Sum0.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Sum0.java
@@ -57,7 +57,8 @@ import java.util.List;
  */
 public class Sum0 extends NotNullableAggregateFunction
         implements UnaryExpression, ExplicitlyCastableSignature, 
ComputePrecisionForSum,
-        SupportWindowAnalytic, RollUpTrait, SupportMultiDistinct, 
NeedSessionVarGuard {
+        SupportWindowAnalytic, RollUpTrait, SupportMultiDistinct, 
NeedSessionVarGuard,
+        NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopN.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopN.java
index f03bbedf343..15b52e8f340 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopN.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopN.java
@@ -35,7 +35,7 @@ import java.util.List;
  * AggregateFunction 'topn'. This class is generated by GenerateFunction.
  */
 public class TopN extends NullableAggregateFunction
-        implements ExplicitlyCastableSignature {
+        implements ExplicitlyCastableSignature, NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(VarcharType.SYSTEM_DEFAULT,
 IntegerType.INSTANCE),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNArray.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNArray.java
index 840f520b876..616c9775412 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNArray.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNArray.java
@@ -37,7 +37,7 @@ import java.util.List;
  * AggregateFunction 'topn_array'. This class is generated by GenerateFunction.
  */
 public class TopNArray extends NullableAggregateFunction
-        implements ExplicitlyCastableSignature {
+        implements ExplicitlyCastableSignature, NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             FunctionSignature.ret(ArrayType.of(new FollowToAnyDataType(0)))
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNWeighted.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNWeighted.java
index 1222fcdac37..6bd5497c3e2 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNWeighted.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNWeighted.java
@@ -50,7 +50,7 @@ import java.util.List;
  * AggregateFunction 'topn_weighted'. This class is generated by 
GenerateFunction.
  */
 public class TopNWeighted extends NullableAggregateFunction
-        implements ExplicitlyCastableSignature {
+        implements ExplicitlyCastableSignature, NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             // three arguments
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Variance.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Variance.java
index 756948ea9eb..f5c49b16ad1 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Variance.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Variance.java
@@ -35,7 +35,7 @@ import java.util.List;
  */
 public class Variance extends NullableAggregateFunction
         implements UnaryExpression, ExplicitlyCastableSignature,
-        StdDevOrVarianceFunction, DecimalStddevPrecision {
+        StdDevOrVarianceFunction, DecimalStddevPrecision, 
NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE));
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/VarianceSamp.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/VarianceSamp.java
index ab3af3e7888..5c2a8581867 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/VarianceSamp.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/VarianceSamp.java
@@ -34,7 +34,7 @@ import java.util.List;
  */
 public class VarianceSamp extends NullableAggregateFunction
         implements UnaryExpression, ExplicitlyCastableSignature,
-        StdDevOrVarianceFunction {
+        StdDevOrVarianceFunction, NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE));
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnel.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnel.java
index 9f152821c2f..6a844b22cdd 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnel.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnel.java
@@ -43,7 +43,7 @@ import java.util.List;
  * AggregateFunction 'window_funnel'. This class is generated by 
GenerateFunction.
  */
 public class WindowFunnel extends NullableAggregateFunction
-        implements ExplicitlyCastableSignature {
+        implements ExplicitlyCastableSignature, NullIgnoringAggregateFunction {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             FunctionSignature.ret(IntegerType.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnelV2.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnelV2.java
index fabca97f744..c6d6bb02212 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnelV2.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnelV2.java
@@ -44,7 +44,7 @@ import java.util.List;
  * as (timestamp, event_index) pairs, dramatically reducing memory usage 
compared to V1.
  */
 public class WindowFunnelV2 extends NullableAggregateFunction
-        implements ExplicitlyCastableSignature {
+        implements ExplicitlyCastableSignature, NullIgnoringAggregateFunction {
 
     public static final int MAX_EVENT_CONDITIONS = 127;
 
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/InferAggNotNullTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/InferAggNotNullTest.java
index 30c17c2dd68..f0e709dc1b7 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/InferAggNotNullTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/InferAggNotNullTest.java
@@ -30,10 +30,18 @@ import org.apache.doris.nereids.trees.expressions.Not;
 import 
org.apache.doris.nereids.trees.expressions.functions.agg.AggregateFunction;
 import org.apache.doris.nereids.trees.expressions.functions.agg.ArrayAgg;
 import org.apache.doris.nereids.trees.expressions.functions.agg.Avg;
+import org.apache.doris.nereids.trees.expressions.functions.agg.BitmapAgg;
+import org.apache.doris.nereids.trees.expressions.functions.agg.CollectList;
 import org.apache.doris.nereids.trees.expressions.functions.agg.Count;
+import org.apache.doris.nereids.trees.expressions.functions.agg.CountByEnum;
+import org.apache.doris.nereids.trees.expressions.functions.agg.GroupConcat;
+import org.apache.doris.nereids.trees.expressions.functions.agg.MapAgg;
+import org.apache.doris.nereids.trees.expressions.functions.agg.MapAggV2;
 import org.apache.doris.nereids.trees.expressions.functions.agg.Max;
 import org.apache.doris.nereids.trees.expressions.functions.agg.Min;
+import 
org.apache.doris.nereids.trees.expressions.functions.agg.NullIgnoringAggregateFunction;
 import org.apache.doris.nereids.trees.expressions.functions.agg.Sum;
+import org.apache.doris.nereids.trees.expressions.functions.agg.Sum0;
 import org.apache.doris.nereids.trees.plans.RelationId;
 import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
 import org.apache.doris.nereids.trees.plans.logical.LogicalOlapScan;
@@ -129,6 +137,32 @@ class InferAggNotNullTest implements 
MemoPatternMatchSupported {
                 );
     }
 
+    @Test
+    void testAuditedNullInputContractMarkers() {
+        Expression key = scan1.getOutput().get(0);
+        Expression value = scan1.getOutput().get(1);
+
+        List<AggregateFunction> nullIgnoring = ImmutableList.of(
+                new Sum(value),
+                new Sum0(value),
+                new CollectList(value),
+                new BitmapAgg(value));
+        nullIgnoring.forEach(function -> Assertions.assertTrue(
+                function instanceof NullIgnoringAggregateFunction,
+                function.getName() + " must declare the audited null-row 
contract"));
+
+        // NotNullableAggregateFunction does not imply that NULL argument rows 
can be removed.
+        List<AggregateFunction> withoutClassWideProof = ImmutableList.of(
+                new ArrayAgg(value),
+                new MapAgg(key, value),
+                new MapAggV2(key, value),
+                new CountByEnum(value),
+                new GroupConcat(value));
+        withoutClassWideProof.forEach(function -> Assertions.assertFalse(
+                function instanceof NullIgnoringAggregateFunction,
+                function.getName() + " must remain conservative until every 
mode is proven"));
+    }
+
     @Test
     void testNullSensitiveAggregateBlocksCommonInference() {
         LogicalPlan plan = new LogicalPlanBuilder(scan1)
diff --git 
a/regression-test/data/nereids_rules_p0/eliminate_aggregate_casewhen/eliminate_aggregate_casewhen.out
 
b/regression-test/data/nereids_rules_p0/eliminate_aggregate_casewhen/eliminate_aggregate_casewhen.out
index 8205077a801..df19fb31688 100644
--- 
a/regression-test/data/nereids_rules_p0/eliminate_aggregate_casewhen/eliminate_aggregate_casewhen.out
+++ 
b/regression-test/data/nereids_rules_p0/eliminate_aggregate_casewhen/eliminate_aggregate_casewhen.out
@@ -175,6 +175,59 @@ PhysicalResultSink
 ----PhysicalProject
 ------PhysicalOlapScan[t4]
 
+-- !array_agg_no_eliminate --
+PhysicalResultSink
+--PhysicalProject
+----hashAgg[GLOBAL]
+------hashAgg[LOCAL]
+--------PhysicalProject
+----------PhysicalOlapScan[t4]
+
+-- !collect_list_eliminate --
+PhysicalResultSink
+--PhysicalProject
+----hashAgg[GLOBAL]
+------hashAgg[LOCAL]
+--------PhysicalProject
+----------filter((t4.c4 = 102))
+------------PhysicalOlapScan[t4]
+
+-- !collect_list_distinct_eliminate --
+PhysicalResultSink
+--PhysicalProject
+----hashAgg[DISTINCT_GLOBAL]
+------hashAgg[DISTINCT_LOCAL]
+--------hashAgg[GLOBAL]
+----------hashAgg[LOCAL]
+------------PhysicalProject
+--------------filter((t4.c4 = 102))
+----------------PhysicalOlapScan[t4]
+
+-- !bool_or_eliminate --
+PhysicalResultSink
+--hashAgg[GLOBAL]
+----hashAgg[LOCAL]
+------PhysicalProject
+--------filter((t4.c4 = 102))
+----------PhysicalOlapScan[t4]
+
+-- !sum0_eliminate --
+PhysicalResultSink
+--hashAgg[GLOBAL]
+----hashAgg[LOCAL]
+------PhysicalProject
+--------filter((t4.c4 = 102))
+----------PhysicalOlapScan[t4]
+
+-- !bitmap_agg_eliminate --
+PhysicalResultSink
+--PhysicalProject
+----hashAgg[GLOBAL]
+------hashAgg[LOCAL]
+--------PhysicalProject
+----------filter((t4.c4 = 102))
+------------PhysicalOlapScan[t4]
+
 -- !basic_1 --
 10
 
@@ -247,3 +300,24 @@ PhysicalResultSink
 102    1
 103    1
 
+-- !array_agg_preserves_null --
+2
+
+-- !array_agg_distinct_preserves_null --
+2
+
+-- !collect_list_ignores_null --
+1
+
+-- !collect_list_distinct_ignores_null --
+1
+
+-- !bool_or_ignores_null --
+true
+
+-- !sum0_ignores_null --
+102
+
+-- !bitmap_agg_ignores_null --
+1
+
diff --git 
a/regression-test/data/nereids_rules_p0/infer_agg_not_null/infer_agg_not_null.out
 
b/regression-test/data/nereids_rules_p0/infer_agg_not_null/infer_agg_not_null.out
index c182c0ba43a..233b9a1b71b 100644
--- 
a/regression-test/data/nereids_rules_p0/infer_agg_not_null/infer_agg_not_null.out
+++ 
b/regression-test/data/nereids_rules_p0/infer_agg_not_null/infer_agg_not_null.out
@@ -11,3 +11,12 @@
 -- !mixed_count_array_agg --
 1      3
 
+-- !null_ignoring_aggregate_identities --
+9      9       1       1
+
+-- !all_null_equals_empty_input --
+\N     \N      0       0       0       0       0       0
+
+-- !null_sensitive_aggregates_keep_rows --
+3      3
+
diff --git 
a/regression-test/suites/nereids_rules_p0/eliminate_aggregate_casewhen/eliminate_aggregate_casewhen.groovy
 
b/regression-test/suites/nereids_rules_p0/eliminate_aggregate_casewhen/eliminate_aggregate_casewhen.groovy
index 8de498cb362..a1b00cdedf6 100644
--- 
a/regression-test/suites/nereids_rules_p0/eliminate_aggregate_casewhen/eliminate_aggregate_casewhen.groovy
+++ 
b/regression-test/suites/nereids_rules_p0/eliminate_aggregate_casewhen/eliminate_aggregate_casewhen.groovy
@@ -75,6 +75,34 @@ suite("eliminate_aggregate_casewhen") {
     qt_basic_4_5 """explain shape plan select count(case when t4.c4 > 100 then 
10 end) from t4;"""
     qt_basic_4_6 """explain shape plan select t4.c4, count(case when t4.c4 > 
100 then 10 end) from t4 group by t4.c4;"""
 
+    // NULL-preserving aggregates must keep the IF expression and all input 
rows.
+    qt_array_agg_no_eliminate """
+        explain shape plan
+        select array_size(array_agg(case when t4.c4 = 102 then t4.c4 end)) 
from t4;
+    """
+
+    // Audited NULL-ignoring aggregates remain eligible for the rewrite.
+    qt_collect_list_eliminate """
+        explain shape plan
+        select array_size(collect_list(case when t4.c4 = 102 then t4.c4 end)) 
from t4;
+    """
+    qt_collect_list_distinct_eliminate """
+        explain shape plan
+        select array_size(collect_list(distinct case when t4.c4 = 102 then 
t4.c4 end)) from t4;
+    """
+    qt_bool_or_eliminate """
+        explain shape plan
+        select bool_or(case when t4.c4 = 102 then cast(t4.c4 as boolean) end) 
from t4;
+    """
+    qt_sum0_eliminate """
+        explain shape plan
+        select sum0(case when t4.c4 = 102 then t4.c4 end) from t4;
+    """
+    qt_bitmap_agg_eliminate """
+        explain shape plan
+        select bitmap_count(bitmap_agg(case when t4.c4 = 102 then t4.c4 end)) 
from t4;
+    """
+
     /* ******** Output ******** */
 
     /* ******** with one row ******** */
@@ -108,4 +136,26 @@ suite("eliminate_aggregate_casewhen") {
     order_qt_basic_4_4 """select max(case when t4.c4 > 100 then 10 end) from 
t4;"""
     order_qt_basic_4_5 """select count(case when t4.c4 > 100 then 10 end) from 
t4;"""
     order_qt_basic_4_6 """select t4.c4, count(case when t4.c4 > 100 then 10 
end) from t4 group by t4.c4;"""
+
+    order_qt_array_agg_preserves_null """
+        select array_size(array_agg(case when t4.c4 = 102 then t4.c4 end)) 
from t4;
+    """
+    order_qt_array_agg_distinct_preserves_null """
+        select array_size(array_agg(distinct case when t4.c4 = 102 then t4.c4 
end)) from t4;
+    """
+    order_qt_collect_list_ignores_null """
+        select array_size(collect_list(case when t4.c4 = 102 then t4.c4 end)) 
from t4;
+    """
+    order_qt_collect_list_distinct_ignores_null """
+        select array_size(collect_list(distinct case when t4.c4 = 102 then 
t4.c4 end)) from t4;
+    """
+    order_qt_bool_or_ignores_null """
+        select bool_or(case when t4.c4 = 102 then cast(t4.c4 as boolean) end) 
from t4;
+    """
+    order_qt_sum0_ignores_null """
+        select sum0(case when t4.c4 = 102 then t4.c4 end) from t4;
+    """
+    order_qt_bitmap_agg_ignores_null """
+        select bitmap_count(bitmap_agg(case when t4.c4 = 102 then t4.c4 end)) 
from t4;
+    """
 }
diff --git 
a/regression-test/suites/nereids_rules_p0/infer_agg_not_null/infer_agg_not_null.groovy
 
b/regression-test/suites/nereids_rules_p0/infer_agg_not_null/infer_agg_not_null.groovy
index 56b9ec535b7..742e9771fb8 100644
--- 
a/regression-test/suites/nereids_rules_p0/infer_agg_not_null/infer_agg_not_null.groovy
+++ 
b/regression-test/suites/nereids_rules_p0/infer_agg_not_null/infer_agg_not_null.groovy
@@ -63,6 +63,31 @@ suite("infer_agg_not_null") {
         LEFT JOIN infer_agg_not_null_right r ON l.k = r.k
     """
 
+    order_qt_null_ignoring_aggregate_identities """
+        SELECT SUM(r.v), SUM0(r.v), ARRAY_SIZE(COLLECT_LIST(r.v)),
+               BITMAP_COUNT(BITMAP_AGG(r.v))
+        FROM infer_agg_not_null_left l
+        LEFT JOIN infer_agg_not_null_right r ON l.k = r.k
+    """
+
+    order_qt_all_null_equals_empty_input """
+        SELECT
+            (SELECT SUM(v) FROM infer_agg_not_null_right WHERE k = 3),
+            (SELECT SUM(v) FROM infer_agg_not_null_right WHERE FALSE),
+            (SELECT SUM0(v) FROM infer_agg_not_null_right WHERE k = 3),
+            (SELECT SUM0(v) FROM infer_agg_not_null_right WHERE FALSE),
+            (SELECT ARRAY_SIZE(COLLECT_LIST(v)) FROM infer_agg_not_null_right 
WHERE k = 3),
+            (SELECT ARRAY_SIZE(COLLECT_LIST(v)) FROM infer_agg_not_null_right 
WHERE FALSE),
+            (SELECT BITMAP_COUNT(BITMAP_AGG(v)) FROM infer_agg_not_null_right 
WHERE k = 3),
+            (SELECT BITMAP_COUNT(BITMAP_AGG(v)) FROM infer_agg_not_null_right 
WHERE FALSE)
+    """
+
+    order_qt_null_sensitive_aggregates_keep_rows """
+        SELECT ARRAY_SIZE(ARRAY_AGG(r.v)), MAP_SIZE(MAP_AGG(l.k, r.v))
+        FROM infer_agg_not_null_left l
+        LEFT JOIN infer_agg_not_null_right r ON l.k = r.k
+    """
+
     explain {
         sql """
             SHAPE PLAN
@@ -102,4 +127,26 @@ suite("infer_agg_not_null") {
         """
         contains "LEFT_OUTER_JOIN"
     }
+
+    explain {
+        sql """
+            SHAPE PLAN
+            SELECT SUM(r.v), SUM0(r.v), ARRAY_SIZE(COLLECT_LIST(r.v)),
+                   BITMAP_COUNT(BITMAP_AGG(r.v))
+            FROM infer_agg_not_null_left l
+            LEFT JOIN infer_agg_not_null_right r ON l.k = r.k
+        """
+        contains "INNER_JOIN"
+        notContains "LEFT_OUTER_JOIN"
+    }
+
+    explain {
+        sql """
+            SHAPE PLAN
+            SELECT ARRAY_SIZE(ARRAY_AGG(r.v)), MAP_SIZE(MAP_AGG(l.k, r.v))
+            FROM infer_agg_not_null_left l
+            LEFT JOIN infer_agg_not_null_right r ON l.k = r.k
+        """
+        contains "LEFT_OUTER_JOIN"
+    }
 }


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

Reply via email to