-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
MDEV-24943: Implement FILTER clause support for aggregate functions #4439
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
9f3c0ff to
cb7d38d
Compare
|
Thank for taking the effort to work on this. Indeed, the LIMIT clause is a part of (at least) SQL 2011 and, as such, is a very good feature to have. However, the diff seems very incomplete. Can you please make sure that you:
Please re-submit when you have the above. |
|
I don't see how the diff is incomplete. It applies fine. It compiles fine. It passes tests on buildbot, not every builder, but it passes on many builders, this doesn't look like a non-working diff. |
|
Hi @KhaledR57 , I'm experimenting with the changes and I see a difference between what should otherwise be equivalent statements. What was once written using However, on MariaDB, the Why is this the case? |
|
If we store the sequence engine result to an InnoDB-backed table and run the FILTER query against that instead we get the correct result: |
cb7d38d to
aaea60a
Compare
|
Hi @DaveGosselin-MariaDB , Sorry for the delayed response! The issue was with the sequence storage engine's I've added a if (item->type() != Item::SUM_FUNC_ITEM ||
(((Item_sum*) item)->sum_func() != Item_sum::SUM_FUNC &&
((Item_sum*) item)->sum_func() != Item_sum::COUNT_FUNC) ||
((Item_sum*) item)->has_filter()) // NEW CHECK
return 0; // Fall back to normal aggregationStoring the sequence data to an InnoDB table gave the correct result because InnoDB goes through the standard I'll add sequence-specific tests in the next commit after I finish the stored aggregates (almost done with those). |
34ffec1 to
06b76ca
Compare
2e31328 to
0d88cba
Compare
|
Hi @KhaledR57 ,
Will such a change be required for every storage engine? If so, is there a way to generalize this for every storage engine? |
DaveGosselin-MariaDB
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @KhaledR57 ,
Here are the places I found in your patch which are not exercised by your new tests. Please add test cases that exercise them. Feel free to reach out to me on Zulip if you need help. I still have more review work to do and will update again soon.
Thanks,
Dave
| if (filter_expr->type() == Item::SUM_FUNC_ITEM || | ||
| filter_expr->type() == Item::WINDOW_FUNC_ITEM) | ||
| { | ||
| my_error(ER_WRONG_USAGE, MYF(0), "aggregate function", "FILTER"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This codepath isn't exercised by your new tests.
| @@ -1698,7 +1774,7 @@ void Item_sum_sum::add_helper(bool perform_removal) | |||
| sum-= aggr->arg_val_real(); | |||
| else | |||
| sum+= aggr->arg_val_real(); | |||
| if (!aggr->arg_is_null(true)) | |||
| if (!aggr->arg_is_null(true) && filter_passed()) | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This codepath isn't exercised by your new tests.
| @@ -2336,7 +2412,7 @@ void Item_sum_variance::reset_field() | |||
|
|
|||
| nr= args[0]->val_real(); /* sets null_value as side-effect */ | |||
|
|
|||
| if (args[0]->null_value) | |||
| if (args[0]->null_value || !filter_passed()) | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This codepath isn't exercised by your new tests.
| @@ -2367,7 +2443,7 @@ void Item_sum_variance::update_field() | |||
|
|
|||
| double nr= args[0]->val_real(); /* sets null_value as side-effect */ | |||
|
|
|||
| if (args[0]->null_value) | |||
| if (args[0]->null_value || !filter_passed()) | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This codepath isn't exercised by your new tests.
| @@ -2641,7 +2717,7 @@ bool Item_sum_bit::clear_as_window() | |||
| bool Item_sum_bit::remove_as_window(ulonglong value) | |||
| { | |||
| DBUG_ASSERT(as_window_function); | |||
| if (num_values_added == 0) | |||
| if (num_values_added == 0 || args[0]->null_value || !filter_passed()) | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This codepath isn't exercised by your new tests.
| @@ -3021,7 +3106,7 @@ void Item_sum_sum::update_field() | |||
| else | |||
| { | |||
| nr= args[0]->val_real(); | |||
| null_flag= args[0]->null_value; | |||
| null_flag= args[0]->null_value || !filter_passed(); | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This codepath isn't exercised by your new tests.
| @@ -3045,7 +3130,7 @@ void Item_sum_count::update_field() | |||
| direct_counted= direct_reseted_field= FALSE; | |||
| nr+= direct_count; | |||
| } | |||
| else if (!args[0]->maybe_null() || !args[0]->is_null()) | |||
| else if ((!args[0]->maybe_null() || !args[0]->is_null()) && filter_passed()) | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This codepath isn't exercised by your new tests.
| @@ -3080,7 +3165,7 @@ void Item_sum_avg::update_field() | |||
| double nr; | |||
|
|
|||
| nr= args[0]->val_real(); | |||
| if (!args[0]->null_value) | |||
| if (!args[0]->null_value && filter_passed()) | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This codepath isn't exercised by your new tests.
| @@ -4639,7 +4734,7 @@ bool Item_func_collect::add() { | |||
| uint current_geometry_srid; | |||
| has_cached_result= false; | |||
|
|
|||
| if (tmp_arg[0]->null_value) | |||
| if (tmp_arg[0]->null_value || !filter_passed()) | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This codepath isn't exercised by your new tests.
| @@ -4663,7 +4758,7 @@ void Item_func_collect::remove() { | |||
| String *wkb= args[0]->val_str(&value); | |||
| has_cached_result= false; | |||
|
|
|||
| if (args[0]->null_value) return; | |||
| if (args[0]->null_value || !filter_passed()) return; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This codepath isn't exercised by your new tests.
Hi @DaveGosselin-MariaDB, |
|
Hi @KhaledR57 , |
Sorry, I wasn't following the ticket. I believe these are already handled. Or the comment meant something else. If I misunderstood something, please let me know. |
Aggregates lacked the SQL-standard FILTER clause, forcing CASE-based workarounds that reduced readability across (sum, avg, count, …). This update introduces the ability to specify a FILTER clause for aggregate functions, allowing for more granular control over which rows are included in the aggregation. Also, improves standards compliance and makes queries clearer and more readable. The FILTER(WHERE ...) condition may contain any expression allowed in regular WHERE clauses, except subqueries, window functions, and outer references.
Avoid freeing SP query arena items when the aggregate function context was never initialized, which could happen if the first group is filtered out by HAVING.
0d88cba to
408db34
Compare
Description
Aggregates lacked the SQL-standard
FILTERclause, forcing CASE-based workarounds that reduced readability.This update introduces the ability to specify a
FILTERclause for aggregate functions, allowing for more granular control over which rows are included in the aggregation. Also, improves standards compliance and makes queries clearer and more readable.The
<condition>may contain any expression allowed in regularWHEREclauses, exceptsubqueries, window functions, and outer references.Example:
How can this PR be tested?
Running the Test Suite
Basing the PR against the correct MariaDB version
mainbranch.PR quality check