-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Panache Hibernate adapting query count based on distinct keyword #38316
base: main
Are you sure you want to change the base?
Conversation
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.
It seems fine, but I wouldn't merge it without a test case.
I think there are errors in tests that I need to check and fix. And on top on that add a specific test indeed. This is still a work in progress I suppose :) |
Thanks @rysurd, that's fine. But it's usually better to send a PR when one also has a test case. It saves everybody's time. |
87406db
to
49aaeb6
Compare
Hello @DavideD ! I updated my PR with two main changes ;
java.lang.IllegalArgumentException: org.hibernate.query.SemanticException: Select item at position 1 in select list has no alias (aliases are required in CTEs and in subqueries occurring in from clause) I also added one another test in TestEndpoint for projection ; we also check distinct query for projection on Long, just like in the original issue. |
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.
Unless I'm missing something, this solution doesn't seem correct.
The issue is about generating a query like:
select count(distinct entity.id) from ...
but you are creating the following query instead:
select count(*) from (select distinct entity.id from ... )
Also, if existing tests don't work any more after applying your fix, it means there's something wrong with your solution. You shouldn't change them to make your solution work.
If we apply this solution, what do you think it will happen to the apps running distinct queries without aliases after the upgrade?
@@ -1326,7 +1326,7 @@ public String testProjection() { | |||
|
|||
PanacheQuery<CatProjectionBean> projectionDistinctQuery = Cat | |||
// The spaces at the beginning are intentional | |||
.find(" SELECT disTINct c.name, cast(null as string), SUM(c.weight) from Cat c where name = :name group by name ", | |||
.find(" SELECT disTINct c.name as foo, cast(null as string) as bar, SUM(c.weight) as baz from Cat c where name = :name group by name ", |
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 is suspicious, why this test suddenly requires a change?
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.
Yeah, this should keep working.
// We are checking that not everything gets lowercased | ||
PanacheQuery<CatProjectionBean> letterCaseQuery = Cat | ||
// The spaces at the beginning are intentional | ||
.find(" SELECT disTINct 'GARFIELD', 'JoN ArBuCkLe' from Cat c where name = :NamE group by name ", | ||
.find(" SELECT disTINct 'GARFIELD' as foo, 'JoN ArBuCkLe' as bar from Cat c where name = :NamE group by name ", |
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 is suspicious, why this test suddenly requires a change?
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.
+1
So indeed I wanted to implement a query like the first one you suggested. It work for cases where you want to distinct count on one column. However it fails when we have aggregate function (like SUM) or when we want to count distinct on multiple columns. If you plainly put the input select clauses in the distinct statement you can end up having a query like this for instance select count(distinct entity.id, SUM(entity.weight)) from ... It'll generate an error (This one https://github.com/rysurd/quarkus/actions/runs/7628145894/job/20778994932#step:16:3219). So this is why I went rather for moving the distinct statement in a subquery in the from statement. Maybe (probably) I'm the one missing out something here that would make this work 😄
I'd agree that something can be wrong with the solution, but this could also mean we didn't took some edge case into consideration when writing the tests, in can happen sometimes. In any case if you can help me understand the previous problem about aggregate function in subquery I'd appreciate ! I'll keep working on this issue and will try to find another solution. Thanks a lot! EDIT : Also I'm not sure we can have distinct count on multiple columns right from the select statement with Hibernate |
It seems we did in this case, otherwise CI wouldn't fail.
I see now. Alternatives I can think of is to split by Or, add an attribute to @gsmet, If we decide to go for this approach, this is a breaking change that will make queries not using an alias fail.
I'm not sure, but I'm assuming that when having subqueries, you have to specify which field of which entity you refer to because you could have a reference to the same entity multiple times. |
I think this could be a solution, I'd even like to try to implement it just to see. But yeah, I think unless we missed something there is no straightforward solution to the problem ... Let's see what @gsmet thinks. |
This solution is not really different from what we did in other places, though |
Hello. While I agree this is a bug, I'm skeptical about what the behaviour of
At this point, it's already unclear what projections do in the case of a no-op. Should we really generate I don't even know if this works. In any case, there's definitely a bug because since this is a no-op, the count method should be the same as the original one, and it's not the case. Now, given that the logic is duplicated in ORM, HR and Mongo, a fix should also include the other queries. Though in the case of Mongo, it doesn't appear to need a fix. As to whether we need a real parser for this, I'm seriously starting to wonder if we should not start a discussion with @gavinking about the new shorter queries supported in HQL, and adding feature methods like project and count to any query types of ORM/HR if they're missing there. And let them deal with the parsing and all. This is bound to be better for both ORM and us. |
@@ -1326,7 +1326,7 @@ public String testProjection() { | |||
|
|||
PanacheQuery<CatProjectionBean> projectionDistinctQuery = Cat | |||
// The spaces at the beginning are intentional | |||
.find(" SELECT disTINct c.name, cast(null as string), SUM(c.weight) from Cat c where name = :name group by name ", | |||
.find(" SELECT disTINct c.name as foo, cast(null as string) as bar, SUM(c.weight) as baz from Cat c where name = :name group by name ", |
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.
Yeah, this should keep working.
// We are checking that not everything gets lowercased | ||
PanacheQuery<CatProjectionBean> letterCaseQuery = Cat | ||
// The spaces at the beginning are intentional | ||
.find(" SELECT disTINct 'GARFIELD', 'JoN ArBuCkLe' from Cat c where name = :NamE group by name ", | ||
.find(" SELECT disTINct 'GARFIELD' as foo, 'JoN ArBuCkLe' as bar from Cat c where name = :NamE group by name ", |
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.
+1
Ah, I missed this.
If possible (I'm not familiar with the new shorter form), I think that would be the best approach. IMHO, Panache should focus on providing a better programmatic DSL (maybe using Criteria and the JPA metamodel, or other libraries underneath) and leave strings parsing to the existing libraries that have been refined over the many years they've been around. |
Do you happen to have any documentation or guide on how to implement these new and shorter HQL queries? Is it done by using Criteria and JPA metamodel as @DavideD suggested before? If indeed it can allow to not deal with SQL parsing we could benefit from it. |
This is a discussion I should have with @gavinking at some point. |
Fix #38033