Skip to content

HHH-3356 Support for normal and lateral subquery in from clause #5086

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 1 commit into from
Jun 4, 2022

Conversation

beikov
Copy link
Member

@beikov beikov commented Jun 2, 2022

https://hibernate.atlassian.net/browse/HHH-3356

This adds support for sub queries in the from clause as roots and joins. Sub queries can have an optional lateral marker, which allows sub queries to refer to previous from clause nodes. Also see the SQL standard definition of LATERAL or the nice documentation text from PostgreSQL for more details: https://www.postgresql.org/docs/current/queries-table-expressions.html#QUERIES-LATERAL

The design follows what was discussed here which is, that tuple types and their model parts are determined based on the select items of a sub query. It is not necessary to define an explicit (managed) type in order to use this feature.

There are a few things missing which are mostly of "mechanical" nature, i.e. someone needs to do it, but there shouldn't be any technical challenge. These will be added to the next bug fix version of 6.1, given that this PR makes it into 6.1. This was done deliberately to be able for this feature to make it into 6.1.

The currently missing parts are:

  • DomainResult support for anonymous tuples i.e. select d from (select ...) d is not supported
  • Correlation support i.e. select ... from (select ...) d where (select ... where d.field = 1) is not supported
  • Support for selecting entity valued paths, where the entity type has an id class or embedded id. See SubQueryInFromEmbeddedIdTests and SubQueryInFromIdClassTests

@beikov beikov added the 6.1 label Jun 2, 2022
@gavinking
Copy link
Member

This looks rather good, assuming I'm understanding everything. A couple of comments:

  • Is there truly an advantage to requiring this explicit lateral? Could it be implicit? Is the reason for making it explicit that it's something that's only supported on one platform?
  • There's lots of tests for lateral, but not so many for plain vanilla from-clause subselects. I would like to see more of the "basic" case, so I can get a better feel for it.

@beikov
Copy link
Member Author

beikov commented Jun 2, 2022

Is there truly an advantage to requiring this explicit lateral? Could it be implicit? Is the reason for making it explicit that it's something that's only supported on one platform?

lateral, or cross apply how SQL server and some other DB vendors are calling this, essentially forces the database to process table scans/joins in a certain order and forces a nested loop join. So this is not something that we can or should do by default. If by implicit, you mean that if we can infer whether lateral is "required", then yes, that would be possible, though I'd say there are valid reasons for wanting to use lateral even if it isn't required.
Either lateral or cross apply are supported on the major DBMS (MySQL 8, PostgreSQL, Oracle, SQL Server, DB2, HSQL, HANA). We have an emulation for it for others DBs, but as you can imagine, it's not pretty and also limited to certain sub query shapes.

Either way, I'd rather not make this the default if that's what you mean by "implicit".

There's lots of tests for lateral, but not so many for plain vanilla from-clause subselects. I would like to see more of the "basic" case, so I can get a better feel for it.

I'll add a few more tests if that makes you feel better ;)

@gavinking
Copy link
Member

forces the database to process table scans/joins in a certain order and forces a nested loop join. So this is not something that we can or should do by default.

Well yeah but I'm not suggesting to generate the lateral keyword by default. I'm suggesting to automatically detect when it's required. Which seems straightforward?

@beikov
Copy link
Member Author

beikov commented Jun 2, 2022

Well yeah but I'm not suggesting to generate the lateral keyword by default. I'm suggesting to automatically detect when it's required. Which seems straightforward?

Right, we can determine this, but I wouldn't say it is "straightforward". The problem here is that JPA Criteria seems to allow accessing paths from the outer query regardless if the path base is correlated, so the check is not as simple as determining whether the set of correlated nodes is non-empty. We'd have to traverse the whole query tree to be sure. Maybe we could do that somehow during SQM->SQL AST translation, but it's not like I can just grab a flag from somewhere and do something like isLateral() || isCorrelated(). I can add this improvement to the list of things to do for 6.1.1 though.

@beikov beikov merged commit 341267b into hibernate:main Jun 4, 2022
@beikov beikov deleted the HHH-3356 branch June 4, 2022 17:07
@Ablazzing
Copy link

Ablazzing commented Jan 16, 2025

@beikov Hi Christian.
I try to use your fix for subqueries in from clause and see one problem:
You always need to choose aliases for columns in subqueries.
Its kinda weird:
String mainQuery = "select e from (select p from Place p) e - will not working, because you need to make alias for 'select p'.
Exception will be:
Caused by: 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)

So real working case only when you use column names and creating aliases:
select e.name from (select name as name from Place place) e

But it is not working if you dont use aliase for name:
select e.name from (select name from Place place) e

@beikov
Copy link
Member Author

beikov commented Jan 16, 2025

Correct, there is no alias inference based on the expression yet, but the exception message is pretty clear and you have figured out how to make it work. Also, if you have questions, please create a topic on our discussion platform.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants