github-actions[bot] commented on code in PR #64624:
URL: https://github.com/apache/doris/pull/64624#discussion_r3671170638


##########
regression-test/suites/query_p0/aggregate/support_type/percentile/percentile.groovy:
##########
@@ -62,6 +62,45 @@ suite("percentile") {
     qt_percentile_largeint """select percentile(col_largeint, 0.5) from 
d_table;"""
     qt_percentile_float """select percentile(col_float, 0.5) from d_table;"""
     qt_percentile_double """select percentile(col_double, 0.5) from d_table;"""
+    qt_percentile_distinct_const_arg """select percentile(distinct col_double, 
cast('0.5' as double)) from d_table;"""
+    sql """set debug_skip_fold_constant=true;"""
+    qt_percentile_const_expr_materialized """select percentile(col_double, 
coalesce(cast(null as double), cast(0.5 as double))) from d_table;"""
+    test {
+        // NormalizeRepeat materializes the constant expression as a Slot in 
old FE plans.
+        sql """select percentile(col_double, 0.1 + 0.1) from d_table group by 
grouping sets ((k1), ());"""
+    }
+    sql """set enable_aggregate_function_null_v2=false;"""
+    qt_percentile_const_nullable_null_v1 """select percentile(col_double, 
coalesce(cast(null as double), cast(null as double))) from d_table;"""
+    sql """set enable_aggregate_function_null_v2=true;"""
+    qt_percentile_const_nullable_null_v2 """select percentile(col_double, 
coalesce(cast(null as double), cast(null as double))) from d_table;"""
+    sql """set enable_aggregate_function_null_v2=false;"""
+    sql """set debug_skip_fold_constant=false;"""
+
+    sql """drop table if exists percentile_nullable_t;"""
+    sql """
+    create table percentile_nullable_t (
+        id int,
+        v double null
+    ) duplicate key(id)
+    distributed by hash(id) buckets 1
+    properties("replication_num" = "1");
+    """
+    sql """
+    insert into percentile_nullable_t values
+        (1, null),
+        (2, 1.0),
+        (3, 2.0);
+    """
+    sql """set enable_aggregate_function_null_v2=false;"""
+    qt_percentile_nullable_input_v1 """select percentile(v, 0.5) from 
percentile_nullable_t;"""
+    order_qt_percentile_window_nullable_v1 """select id, percentile(v, 0.5) 
over(order by id rows between 1 preceding and current row) from 
percentile_nullable_t order by id;"""
+    sql """set debug_skip_fold_constant=true;"""
+    order_qt_percentile_window_const_expr """select id, percentile(v, 
coalesce(cast(null as double), cast(0.5 as double))) over(order by id rows 
between 1 preceding and current row) from percentile_nullable_t order by id;"""
+    sql """set debug_skip_fold_constant=false;"""
+    sql """set enable_aggregate_function_null_v2=true;"""
+    qt_percentile_nullable_input_v2 """select percentile(v, 0.5) from 
percentile_nullable_t;"""
+    order_qt_percentile_window_nullable_v2 """select id, percentile(v, 0.5) 
over(order by id rows between 1 preceding and current row) from 
percentile_nullable_t order by id;"""
+    sql """set enable_aggregate_function_null_v2=false;"""

Review Comment:
   [P2] This leaves the suite on the legacy null-v1 implementation after the 
paired v1/v2 checks. The session-variable default is `true`, so all of the 
pre-existing NaN percentile cases below now silently stop exercising the 
default null-v2 wrapper. Please restore `true` (or the captured prior value) 
here so the added comparison does not change the remaining suite's coverage.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/AggCombinerFunctionBuilder.java:
##########
@@ -138,6 +139,11 @@ public Pair<BoundFunction, AggregateFunction> build(String 
name, List<?> argumen
             if (!arguments.isEmpty() && arguments.get(0) instanceof Boolean && 
(Boolean) arguments.get(0)) {
                 arguments = arguments.subList(1, arguments.size());
             }
+            // AIAgg's two-argument constructor injects the default resource 
into the nested function.
+            // Include it in the state arguments because BE always consumes 
[resource, input, task].
+            if (nestedFunction instanceof AIAgg && arguments.size() == 2) {
+                arguments = nestedFunction.getArguments();

Review Comment:
   [P1] This makes the default-resource `ai_agg_state(input, task)` form bind, 
but it still cannot execute. The BE scalar `_state` path constructs 
`FunctionAggState` without ever calling `set_query_context()` on the nested 
aggregate; serialization creates `AggregateFunctionAIAggData` with a null 
context, and its first `add()` dereferences `_ctx` while loading AI resources. 
Please propagate the current query context into the nested aggregate for 
FunctionAggState (including nullable wrappers) and add a runtime serialization 
test for this newly reachable form.



##########
be/src/exprs/aggregate/aggregate_function_null.h:
##########
@@ -606,11 +633,23 @@ class AggregateFunctionNullVariadicInline final
 
     void add(AggregateDataPtr __restrict place, const IColumn** columns, 
ssize_t row_num,
              Arena& arena) const override {
+        if (this->check_always_const_col_has_null(columns)) {

Review Comment:
   [P2] This adds an extra full argument scan to every row handled by a 
variadic nullable aggregate, even when the nested function has no 
semantic-constant arguments (the common case for functions such as 
`covar_pop`). The inherited keyed, selected, single-place, range, and streaming 
helpers all dispatch through this `add()`, so the redundant scan is on the core 
aggregation hot path. Please fold the constant-NULL check into the existing 
argument loop, or precompute/retain only nullable semantic-constant indexes and 
bypass it entirely when that set is empty.



##########
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/DistinctAggregateRewriterTest.java:
##########
@@ -245,6 +248,31 @@ void testMultiDistinct() {
         connectContext.getSessionVariable().setAggPhase(0);
     }
 
+    @Test
+    void testDistinctAggregatePreservesNonLiteralConstantArguments() {
+        assertOptimizeSuccess(
+                "select percentile(distinct a, cast('0.5' as double)) from 
test.distinct_agg_split_t");
+        assertOptimizeSuccess(
+                "select percentile_approx(distinct a, cast('0.5' as double), 
cast('2048' as double)) "
+                        + "from test.distinct_agg_split_t");
+        assertOptimizeSuccess(
+                "select percentile_array(distinct a, array(cast('0.5' as 
double), cast('0.8' as double))) "
+                        + "from test.distinct_agg_split_t");
+        assertOptimizeSuccess(
+                "select percentile_reservoir(distinct a, cast('0.5' as 
double)) "
+                        + "from test.distinct_agg_split_t");
+    }
+
+    @Test
+    void testAIAggDistinctIgnoresResourceAndTaskArguments() {
+        SlotReference input = new SlotReference("input", StringType.INSTANCE);
+        AIAgg aiAgg = new AIAgg(new StringLiteral("resource"), input, new 
StringLiteral("task"))
+                .withDistinctAndChildren(true, ImmutableList.of(
+                        new StringLiteral("resource"), input, new 
StringLiteral("task")));
+
+        Assertions.assertEquals(ImmutableList.of(input), 
aiAgg.getDistinctArguments());

Review Comment:
   [P1] This assertion cannot pass with the production implementation in this 
patch. `AIAgg` does not override `getDistinctArguments()`, so the inherited 
method returns all three arguments for a DISTINCT call (`resource`, `input`, 
and `task`), not just `input`. This also makes the resource/task values 
participate as DISTINCT keys. Please implement the AIAgg-specific 
distinct-argument contract (while separately preserving the literals through 
normalization) so this test and the planner agree.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to