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 8cebfdebfda [fix](nereids) fix rewrite avg to sum / count change
nullable (#53787)
8cebfdebfda is described below
commit 8cebfdebfda1f409e9afdbb1b8d5c0877906a900
Author: yujun <[email protected]>
AuthorDate: Thu Jul 24 19:54:42 2025 +0800
[fix](nereids) fix rewrite avg to sum / count change nullable (#53787)
### What problem does this PR solve?
for sql
select avg(distinct a), sum(distinct b) from t group by c
if "a" is not nullable, then "avg" is not nullable,
AvgDistinctToSumDivCount will rewrite "avg" to
"sum(distinct a) / count(distinct a)", but the divide "/" is nullable,
then AdjustNullable will throw exception for this changed nullable
(introduced by #52748):
"AdjustNullable convert slot avg(..)#10 from not-nullable to nullable. You
can disable check by set fe_debug = false."
need add a nonNullable function to make the rewritten expression
not-nullable.
---
.../rules/analysis/AvgDistinctToSumDivCount.java | 10 +++++-
.../adjust_nullable/test_adjust_nullable.out | Bin 0 -> 489 bytes
.../adjust_nullable/test_adjust_nullable.groovy | 36 +++++++++++++++++++++
3 files changed, 45 insertions(+), 1 deletion(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/AvgDistinctToSumDivCount.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/AvgDistinctToSumDivCount.java
index dfc4a2c7432..9b612d7299f 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/AvgDistinctToSumDivCount.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/AvgDistinctToSumDivCount.java
@@ -27,6 +27,7 @@ import
org.apache.doris.nereids.trees.expressions.functions.agg.AggregateFunctio
import org.apache.doris.nereids.trees.expressions.functions.agg.Avg;
import org.apache.doris.nereids.trees.expressions.functions.agg.Count;
import org.apache.doris.nereids.trees.expressions.functions.agg.Sum;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.NonNullable;
import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
import org.apache.doris.nereids.util.ExpressionUtils;
import org.apache.doris.nereids.util.TypeCoercionUtils;
@@ -56,7 +57,14 @@ public class AvgDistinctToSumDivCount extends
OneRewriteRuleFactory {
((Avg) function).child()));
Count count = (Count)
TypeCoercionUtils.processBoundFunction(
new Count(true, ((Avg)
function).child()));
- return TypeCoercionUtils.processDivide(new
Divide(sum, count));
+ Expression divide =
TypeCoercionUtils.processDivide(new Divide(sum, count));
+ if (!function.nullable() && divide.nullable())
{
+ // add NonNullable to ensure the result of
divide is not nullable,
+ // otherwise AdjustNullable rule will
throw exception
+ return new NonNullable(divide);
+ } else {
+ return divide;
+ }
}));
if (!avgToSumDivCount.isEmpty()) {
List<NamedExpression> newOutput =
agg.getOutputExpressions().stream()
diff --git
a/regression-test/data/nereids_rules_p0/adjust_nullable/test_adjust_nullable.out
b/regression-test/data/nereids_rules_p0/adjust_nullable/test_adjust_nullable.out
new file mode 100644
index 00000000000..05ca7f01e20
Binary files /dev/null and
b/regression-test/data/nereids_rules_p0/adjust_nullable/test_adjust_nullable.out
differ
diff --git
a/regression-test/suites/nereids_rules_p0/adjust_nullable/test_adjust_nullable.groovy
b/regression-test/suites/nereids_rules_p0/adjust_nullable/test_adjust_nullable.groovy
new file mode 100644
index 00000000000..72737cae115
--- /dev/null
+++
b/regression-test/suites/nereids_rules_p0/adjust_nullable/test_adjust_nullable.groovy
@@ -0,0 +1,36 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+suite('test_adjust_nullable') {
+ // test AjustNullable not throw exception:
+ // 'AdjustNullable convert slot xx from not-nullable to nullable. You can
disable check by set fe_debug = false.'
+ // NOTICE: the pipeline need set global fe_debug = true
+ def tbl = 'test_adjust_nullable_t'
+ sql "SET detail_shape_nodes='PhysicalProject'"
+ sql "DROP TABLE IF EXISTS ${tbl} FORCE"
+ sql "CREATE TABLE ${tbl}(a int not null, b int, c int not null)
distributed by hash(a) properties('replication_num' = '1')"
+ sql "INSERT INTO ${tbl} VALUES(1, 2, 3)"
+
+ // avg => sum / count
+ // avg is not nullable, while divide '/' is nullable, need add
non_nullable
+ // avg => non_nullable(sum / count)
+ qt_avg_shape """explain shape plan
+ SELECT AVG(distinct a), AVG(distinct b) FROM ${tbl} GROUP BY c
+ """
+
+ sql "DROP TABLE IF EXISTS ${tbl} FORCE"
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]