Skip to content

Refactor bit aggregate functions signature - #18593

Merged
Jefffrey merged 1 commit into
apache:mainfrom
Jefffrey:refactor-bit-agg-sig
Nov 12, 2025
Merged

Jefffrey merged 1 commit into
apache:mainfrom
Jefffrey:refactor-bit-agg-sig

Conversation

@Jefffrey

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Part of #18092

Rationale for this change

Use simpler coercion API.

What changes are included in this PR?

Use coercion API for bit aggregate functions(bit_and, bit_or, bit_xor), instead of enumerating numeric types.

Handle Null datatype explicitly in above functions.

Introduce NoopAccumulator for easier handling of the above.

Are these changes tested?

Existing tests.

Are there any user-facing changes?

No.

@github-actions github-actions Bot added sqllogictest SQL Logic Tests (.slt) functions Changes to functions implementation labels Nov 10, 2025
Comment on lines -231 to +235
signature: Signature::uniform(1, INTEGERS.to_vec(), Volatility::Immutable),
signature: Signature::coercible(
vec![Coercion::new_exact(TypeSignatureClass::Integer)],
Volatility::Immutable,
),

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Main change here; a consequence is DataType::Null input comes in as DataType::Null instead of previously being casted to DataType::Int8.

macro_rules! downcast_bitwise_accumulator {
($args:ident, $opr:expr, $is_distinct: expr) => {
match $args.return_field.data_type() {
DataType::Null => Ok(Box::new(NoopAccumulator::default())),

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handling of Null input type; introduce a new NoopAccumulator which can be used for other aggregate functions, like approx_distinct

default_accumulator_impl!();
}

impl Accumulator for NullHLLAccumulator {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically unrelated to the main change, but since I introduce NoopAccumulator I figured it would be good to use it in other places too, so refactored this.

Comment on lines +22 to +32
/// [`Accumulator`] that does no work and always returns a fixed value (default
/// of `NULL` but can be customized).
///
/// Useful for aggregate functions that need to handle an input of [`DataType::Null`]
/// that does no work.
///
/// [`DataType::Null`]: arrow::datatypes::DataType::Null
#[derive(Debug)]
pub struct NoopAccumulator {
evaluate_value: ScalarValue,
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked into other ideas like trying to implement simplify on AggregateUDFImpl to return Null directly instead of having this noop accumulator but couldn't get it to work; figured can at least centralize this boilerplate and look into easier/more ergonomic handling of pure null inputs for UDFs later


fn state_fields(&self, args: StateFieldsArgs) -> Result<Vec<FieldRef>> {
if self.operation == BitwiseOperationType::Xor && args.is_distinct {
if args.input_fields[0].data_type().is_null() {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needing to change state_fields is not desirable, but until we can make accumulators own state_fields (instead of the function) this will have to do

Comment on lines -7137 to +7151
query I??III?T
query I??????T
select count(null), min(null), max(null), bit_and(NULL), bit_or(NULL), bit_xor(NULL), nth_value(NULL, 1), string_agg(NULL, ',');
----
0 NULL NULL NULL NULL NULL NULL NULL

query TTT
SELECT arrow_typeof(bit_and(NULL)), arrow_typeof(bit_or(NULL)), arrow_typeof(bit_xor(NULL))
----
Null Null Null

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note how null inputs now have null output types too

@Jefffrey
Jefffrey marked this pull request as ready for review November 10, 2025 13:33

@alamb alamb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a nice improvement to me -- thank you @Jefffrey

@Jefffrey
Jefffrey added this pull request to the merge queue Nov 12, 2025
Merged via the queue into apache:main with commit aa74ed0 Nov 12, 2025
51 of 52 checks passed
@Jefffrey
Jefffrey deleted the refactor-bit-agg-sig branch November 12, 2025 12:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

functions Changes to functions implementation sqllogictest SQL Logic Tests (.slt)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants