Skip to content

Fix the behavior of HAVING clause #154

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

Merged
merged 2 commits into from
Aug 14, 2024

Conversation

JanJakes
Copy link
Collaborator

The current implementation has a special handling for HAVING clauses without GROUP BY (this is valid in MySQL in some SQL modes). This implementation takes advantage of the equivalence of ungrouped HAVING with WHERE and rewrites such a HAVING <condition> clause to AND <condition>.

However, the current implementation has some issues:

  1. The presence of GROUP BY in a query is incorrectly detected. The detection always fails, and thus every HAVING query is considered to be ungrouped. I added a fix in the first commit.
  2. Rewriting HAVING <condition> to AND <condition> fails with an error near "AND": syntax error when no WHERE is included in the query. This is fixed in the second commit.
  3. When an aggregate function is used in HAVING (e.g, COUNT(*) > 1), the query fails with: misuse of aggregate function COUNT(). This is because aggregate functions can't be used in the WHERE clause. This is fixed in the second commit.

To fix all of these issues, I implemented a fix for the GROUP BY detection (case 1), and changed the rewriting of HAVING <condition> without GROUP BY to GROUP BY 1 HAVING <condition> (which fixes both case 2 and 3).

There is a logic for translating WHERE ... HAVING without GROUP BY
to WHERE ... AND, and this bug was causing that every HAVING was
rewritten to AND, which resulted in GROUP BY ... HAVING queries
like the following one failing:

SELECT name, COUNT(*) as count FROM _tmp_table GROUP BY name HAVING COUNT(*) > 1;
The previous method of translating ungrouped HAVING to "AND" had some problems:

1. If no WHERE was in the query, the query would fail with: `near "AND": syntax error`
2. When an aggregate function was used in having (e.g, COUNT(*) > 1), the query
    would fail with: `misuse of aggregate function COUNT()`

This commit fixes both of these issues.
Copy link
Member

@brandonpayton brandonpayton left a comment

Choose a reason for hiding this comment

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

@JanJakes, this looks good to me, but I am troubled that our previous test set didn't catch that GROUP BY capture was broken. Before merging this, could we also add a dedicated test for GROUP BY without HAVING?

@JanJakes
Copy link
Collaborator Author

@brandonpayton Thanks for checking this!

GROUP BY capture was indeed broken, but not its execution. The capture itself is used only for the HAVING clause.

When you use GROUP BY without HAVING, then the value of has_group_by is not used, the only reason to capture that variable is the HAVING clause. Additionally, the GROUP BY statement itself is never translated to anything. That means that GROUP BY without HAVING works well, and I'm afraid the detection is not really testable with only a GROUP BY statement (I could check the private property has_group_by, I suppose, but then I'm not testing the public API).

The way to test this via the public API is GROUP BY with HAVING, and I guess I added some tests for that.

@brandonpayton brandonpayton merged commit e88a4e5 into WordPress:develop Aug 14, 2024
8 checks passed
@brandonpayton
Copy link
Member

@JanJakes Thanks for the background and explanation. Let's merge this.

@JanJakes JanJakes deleted the group-by-having branch August 15, 2024 06:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants