You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datafusion.apache.org by gi...@apache.org on 2026/09/13 08:03:49 UTC

(datafusion) branch main updated: fix: reject groups accumulator for bit_xor(DISTINCT) (#24989)

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

github-merge-queue[bot] pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion.git


The following commit(s) were added to refs/heads/main by this push:
     new 681705e6fd fix: reject groups accumulator for bit_xor(DISTINCT) (#24989)
681705e6fd is described below

commit 681705e6fdc4ab1c3df7f734e845a409b8797a83
Author: jackylee <qc...@gmail.com>
AuthorDate: Sun Sep 13 07:53:24 2026 +0000

    fix: reject groups accumulator for bit_xor(DISTINCT) (#24989)
    
    ## Which issue does this PR close?
    
    - N/A
    
    ## Rationale for this change
    
    `bit_xor(DISTINCT c)` with `GROUP BY` fails with `column types must
    match schema types, expected List(Int16) but found Int16`:
    `groups_accumulator_supported` ignored `is_distinct`, so the plan got
    the non-distinct groups accumulator while `state_fields` declared the
    `List` state.
    
    ## What changes are included in this PR?
    
    `groups_accumulator_supported` now returns false only for
    `bit_xor(DISTINCT)`, matching `accumulator` and `state_fields`.
    `bit_and` and `bit_or` are idempotent, so they keep the vectorized path.
    
    ## What is the testing strategy for this PR?
    
    Three `aggregate.slt` queries: the two shapes `SingleDistinctToGroupBy`
    does not rewrite (a non-distinct aggregate alongside, a `FILTER`) fail
    on `main`; a `bit_and`/`bit_or` `DISTINCT` row pins the narrower
    predicate.
    
    ## Are there any user-facing changes?
    
    `bit_xor(DISTINCT)` with `GROUP BY` now works. No API change.
    
    ---------
    
    Co-authored-by: Jay Zhan <ja...@gmail.com>
---
 .../functions-aggregate/src/bit_and_or_xor.rs      |  5 ++--
 datafusion/sqllogictest/test_files/aggregate.slt   | 29 ++++++++++++++++++++++
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/datafusion/functions-aggregate/src/bit_and_or_xor.rs b/datafusion/functions-aggregate/src/bit_and_or_xor.rs
index d730a6c1cb..92212b328e 100644
--- a/datafusion/functions-aggregate/src/bit_and_or_xor.rs
+++ b/datafusion/functions-aggregate/src/bit_and_or_xor.rs
@@ -290,8 +290,9 @@ impl AggregateUDFImpl for BitwiseOperation {
         }
     }
 
-    fn groups_accumulator_supported(&self, _args: AccumulatorArgs) -> bool {
-        true
+    fn groups_accumulator_supported(&self, args: AccumulatorArgs) -> bool {
+        // DISTINCT only changes the result of XOR; AND and OR are idempotent
+        !(args.is_distinct && self.operation == BitwiseOperationType::Xor)
     }
 
     fn create_groups_accumulator(
diff --git a/datafusion/sqllogictest/test_files/aggregate.slt b/datafusion/sqllogictest/test_files/aggregate.slt
index edc493cfa1..a4cd3b0ccc 100644
--- a/datafusion/sqllogictest/test_files/aggregate.slt
+++ b/datafusion/sqllogictest/test_files/aggregate.slt
@@ -5123,6 +5123,35 @@ ORDER BY tag
 33 11 NULL 33 11 NULL 33 11 NULL B
 
 
+# bit_xor(DISTINCT) with GROUP BY must not use the non-distinct groups
+# accumulator: for tag A, 5 ^ 5 ^ 9 = 9 but 5 ^ 9 = 12. AND and OR are
+# idempotent, so they keep the groups accumulator.
+statement ok
+create table bit_distinct (c SMALLINT, tag varchar) as values
+  (5, 'A'), (5, 'A'), (9, 'A'), (33, 'B'), (33, 'B');
+
+query IIT
+SELECT bit_xor(DISTINCT c), count(c), tag FROM bit_distinct GROUP BY tag ORDER BY tag;
+----
+12 3 A
+33 2 B
+
+query IT
+SELECT bit_xor(DISTINCT c) FILTER (WHERE c > 4), tag FROM bit_distinct GROUP BY tag ORDER BY tag;
+----
+12 A
+33 B
+
+query IIIT
+SELECT bit_and(DISTINCT c), bit_or(DISTINCT c), count(c), tag FROM bit_distinct GROUP BY tag ORDER BY tag;
+----
+1 13 3 A
+33 33 2 B
+
+statement ok
+drop table bit_distinct;
+
+
 # bit_and_i32
 statement ok
 create table t (c int) as values (4), (7), (15);


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org