namanjain24-sudo opened a new pull request, #25461:
URL: https://github.com/apache/datafusion/pull/25461

   ## Which issue does this PR close?
   
   - Closes #25417.
   
   ## Rationale for this change
   
   `is_single_distinct_agg` requires that every distinct argument in the 
aggregation is the same expression. It checks that by collecting the arguments 
into a set and requiring the set to hold exactly one element:
   
   ```rust
   if *distinct {
       for e in args {
           fields_set.insert(e);
       }
   ```
   
   A call that passes that expression more than once satisfies the check, 
because its arguments collapse to a single entry. `corr(DISTINCT x, x)` is such 
a call, and the rewrite below then assumed one argument per distinct aggregate 
and returned an internal error.
   
   This is also why the neighbouring cases in the issue are unaffected: 
`corr(DISTINCT x, y)` and `corr(DISTINCT x, x + 0.0)` put two entries in the 
set, so the rule bails out early and leaves the plan alone.
   
   ## What changes are included in this PR?
   
   The distinct branch keeps the call's arity, repeating the alias that the 
inner group by produces, so `corr(DISTINCT x, x)` becomes a group by `x` with 
`corr(alias1, alias1)` above it.
   
   That is sound because of the check above. Every distinct argument is the 
same expression, so the distinct argument tuples the call aggregates are 
exactly the distinct values of that expression, which is what grouping by it 
produces.
   
   The assertion stays, now stating the invariant the rewrite actually relies 
on rather than an arity the rule does not enforce. It also covers an empty 
argument list, which would otherwise panic in `args.swap_remove(0)` instead of 
reporting an internal error.
   
   ## What is the testing strategy for this PR?
   
   Rule tests in `single_distinct_to_groupby.rs`:
   
   - `single_distinct_repeated_arg_and_groupby`: `corr(DISTINCT b, b)` is 
rewritten, and the plan keeps both arguments and the original output column 
name.
   - `single_distinct_two_args_and_groupby`: `corr(DISTINCT b, c)` is still 
left alone.
   
   Two queries in `aggregate.slt` cover it end to end. One is `covar_samp`, 
chosen because its value depends on the de-duplication rather than only on the 
absence of the error: over the same input it returns `0.5` with `DISTINCT` and 
`0.333333333333` without, so the expected value pins the semantics.
   
   Measured, rather than assumed:
   
   | check | result |
   | --- | --- |
   | both halves of the fix reverted | the two `aggregate.slt` queries and 
`single_distinct_repeated_arg_and_groupby` fail with an `Assertion failed: 
args.len() == 1` internal error, which is the failure in the issue |
   | the rewrite against a reference the rule does not touch | the same 
aggregates over a manually de-duplicated input return the same values |
   
   `cargo test -p datafusion-optimizer` (915 tests), the sqllogictest suite 
(521 files), and `./ci/scripts/rust_clippy.sh` pass.
   
   ## Are there any user-facing changes?
   
   Queries that failed with an internal error now run. No plan that the rule 
rewrote before is rewritten differently: a single argument call produces the 
same outer aggregate as it did, and the only calls that reach this branch with 
more than one argument are the ones that previously returned the error.
   


-- 
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