Skip to content

Introduce Sum UDAF - #10651

Merged
jayzhan211 merged 50 commits into
apache:mainfrom
jayzhan211:sum-udaf
Jun 3, 2024
Merged

Introduce Sum UDAF#10651
jayzhan211 merged 50 commits into
apache:mainfrom
jayzhan211:sum-udaf

Conversation

@jayzhan211

@jayzhan211jayzhan211 commented May 24, 2024

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Closes #.

Rationale for this change

What changes are included in this PR?

  1. Add AccumulatorArgs to create_groups_accumulator

This PR only introduce Sum UDAF, remove builtin is not included to keep the PR small.

Are these changes tested?

Are there any user-facing changes?

jayzhan211 added 14 commits May 5, 2024 10:59
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
@github-actionsgithub-actionsBot added logical-expr Logical plan and expressions physical-expr Changes to the physical-expr crates optimizer Optimizer rules core Core DataFusion crate labels May 24, 2024
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
@github-actionsgithub-actionsBot added the sqllogictest SQL Logic Tests (.slt) label May 25, 2024
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
@github-actionsgithub-actionsBot added the sql SQL Planner label May 25, 2024

@alambalamb 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 great to me @jayzhan211 -- thank you. I left some small comments, but overall I think it looks really nice.

// Note if this query ever does start working
let err = execute(&ctx, sql).await.unwrap_err();
assert_contains!(err.to_string(), "This feature is not implemented: Aggregate can not be used as a sliding accumulator because `retract_batch` is not implemented: AggregateUDF { inner: AggregateUDF { name: \"time_sum\", signature: Signature { type_signature: Exact([Timestamp(Nanosecond, None)]), volatility: Immutable }, fun: \"<FUNC>\" } }(t.time) ORDER BY [t.time ASC NULLS LAST] ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING");
assert_contains!(err.to_string(), "This feature is not implemented: Aggregate can not be used as a sliding accumulator because `retract_batch` is not implemented: time_sum(t.time) ORDER BY [t.time ASC NULLS LAST] ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING");

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.

that is certainly nicer


/// Coerce arguments of a function call to types that the function can evaluate.
///
/// This function is only called if [`AggregateUDFImpl::signature`] returns [`crate::TypeSignature::UserDefined`]. Most

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.

👍

&[]
}

fn create_sliding_accumulator(

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.

Could we please add some documentation here explaining what this is?

Basically I think this is to allow returning a different Accumulatorinstance that is optimized for sliding windows (e.g. incrementally computing output via https://docs.rs/datafusion/latest/datafusion/logical_expr/trait.Accumulator.html#method.retract_batch

NotSupported,
/// The expression is different from the original expression
Reversed(Arc<dyn AggregateUDFImpl>),
Reversed(Arc<AggregateUDF>),

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.

👍

Comment threaddatafusion/functions-aggregate/src/lib.rs
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
if fun.to_string() == "first_value" || fun.to_string() == "last_value" {
assert_eq!(fun.to_string(), name);
} else {
assert_eq!(fun.to_string(), name.to_uppercase());

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.

I wonder, maybe we should treat udf names case insensitive way. What do you think?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

#10695 track the issue to rename name to lowercase

Comment threaddatafusion/expr/src/expr_schema.rs Outdated
Comment on lines +179 to +182
let data_types = args
.iter()
.map(|e| e.get_type(schema))
.collect::<Result<Vec<_>>>()?;

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.

Do we need this section?. It seems that data_types is already calculated at the outer scope.

Comment on lines +164 to +177
WindowFunctionDefinition::AggregateUDF(udf) => {
let new_types = data_types_with_aggregate_udf(&data_types, udf).map_err(|err| {
plan_datafusion_err!(
"{} and {}",
err,
utils::generate_signature_error_msg(
fun.name(),
fun.signature().clone(),
&data_types
)
)
})?;
Ok(fun.return_type(&new_types)?)
}

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.

Maybe we should bury this check, and conversion inside to the fun.return_type implementation for WindowFunctionDefinition::AggregateUDF not sure though.

@jayzhan211jayzhan211Jun 3, 2024

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I prefer separate coerce_types and return_types given the difference between these two

Comment on lines +197 to +207
let new_types = data_types_with_aggregate_udf(&data_types, fun).map_err(|err| {
plan_datafusion_err!(
"{} and {}",
err,
utils::generate_signature_error_msg(
fun.name(),
fun.signature().clone(),
&data_types
)
)
})?;

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.

Similar comment above applies here


fn order_bys(&self) -> Option<&[PhysicalSortExpr]> {
(!self.ordering_req.is_empty()).then_some(&self.ordering_req)
if self.fun.has_ordering_requirements() && !self.ordering_req.is_empty() {

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.

Even if has_ordering_requirements is not introduced in this PR. I think, with the order_sensitivity API. This API is redundant. I think, it is better to remove this API (in this Pr or in subsequent ones).

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I agree. We can returns None for AggregateOrderSensitivity::Insensitive, ordering_req if others

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Should we change the default order sensitivity to AggregateOrderSensitivity::Insensitive. For example, I think Sum would expect AggregateOrderSensitivity::Insensitive. And, probably only first/last, nth value and agg_order would expect other kinds of AggregateOrderSensitivity

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.

I agree that, for most of the aggregate functions, AggregateOrderSensitivity::Insensitive is the correct behavior. However, I think the safest default choice is AggregateOrderSensitivity::HardRequirement. Also, as long as there is no requirement, default is not important. Hence, I think we can be strict in this choice.

Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
@jayzhan211
jayzhan211 marked this pull request as draft May 31, 2024 14:03
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
@jayzhan211
jayzhan211 marked this pull request as ready for review May 31, 2024 15:09
jayzhan211and others added 2 commits June 3, 2024 09:31
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>

@mustafasrepomustafasrepo 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.

LGTM!. Thanks @jayzhan211 for this PR.

@jayzhan211

Copy link
Copy Markdown
ContributorAuthor

🚀
Thanks @mustafasrepo and @alamb

@alamb

alamb commented Jun 3, 2024

Copy link
Copy Markdown
Contributor

Are we tracking the follow on work (to remove the built in sum) anywhere?

Comment on lines +107 to +109
(AggregateFunction::Sum, _) => {
return internal_err!("Builtin Sum will be removed");
}

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.

Hi @jayzhan211! I saw @alamb already asked the same question here last week. I'd like to follow-up and check if you have any plans to remove this?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

@appletreeisyellow You can checkout main branch it should be removed in #10831

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.

@jayzhan211 Thank you so much! 💯

@jayzhan211jayzhan211 mentioned this pull request Jul 2, 2024
findepi pushed a commit to findepi/datafusion that referenced this pull request Jul 16, 2024
* move accumulate
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* move prim_op
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* move test to slt
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* remove sum distinct
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* move sum aggregate
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* fix args
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* add sum
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* merge fix
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* fix sum sig
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* todo: wait ahash merge
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* rebase
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* disable ordering req by default
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* check arg count
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* rm old workflow
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* fmt
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* fix failed test
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* doc and fmt
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* check udaf first
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* fmt
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* fix ci
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* fix ci
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* fix ci
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* fix err msg AGAIN
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* rm sum in builtin test which covered in sql
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* proto for window with udaf
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* fix slt
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* fmt
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* fix err msg
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* fix exprfn
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* fix ciy
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* fix ci
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* rename first/last to lowercase
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* skip sum
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* fix firstvalue
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* clippy
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* add doc
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* rm has_ordering_req
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* default hard req
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* insensitive for sum
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* cleanup duplicate code
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
* Re-introduce check
---------
Signed-off-by: jayzhan211 <jayzhan211@gmail.com>
Co-authored-by: Mustafa Akur <mustafa.akur@synnada.ai>
vgapeyev added a commit to sdf-labs/sql-functions that referenced this pull request Aug 26, 2024
apache/datafusion#10651
Don't know if the built-in sum used to work on intervals, but the UDAF does not.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api changeChanges the API exposed to users of the cratecoreCore DataFusion cratelogical-exprLogical plan and expressionsoptimizerOptimizer rulesphysical-exprChanges to the physical-expr cratessqlSQL PlannersqllogictestSQL Logic Tests (.slt)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jayzhan211@alamb@appletreeisyellow@mustafasrepo