Skip to content
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

Add support for joining a subquery in hql #2551

Merged
merged 21 commits into from
Oct 31, 2022

Conversation

maca88
Copy link
Contributor

@maca88 maca88 commented Sep 17, 2020

Basic hql syntax:

from Order o 
inner join (
  from Order where OrderId = 10248
) o2 on (o.OrderId - 1) = o2.OrderId

In case the subquery returns multiple values, each value can be referenced by using an alias:

select o, o2.ord, o2.cu
from Order o 
inner join (
  select o1 as ord, o1.Customer as cu
  from Order o1 where o1.OrderId = 10248
) o2 on (o.OrderId - 1) = o2.ord.OrderId

Aliases can be nested in case of nested subqueries:

select 
  o4.ord3, o4.ord3.ShippedTo, o4.cu3, o4.ord3.ShippingAddress.City,
  o4.sub2.ord2, o4.sub2.ord2.ShippedTo, o4.sub2.cu2, o4.sub2.cu2.Address.City,
  o4.sub2.sub1.ord1, o4.sub2.sub1.ord1.ShippedTo, o4.sub2.sub1.cu1, o4.sub2.sub1.cu1.Address.City
from Order o5
inner join (
  select o as ord3, o.Customer as cu3, o3 as sub2
  from Order o
  left join (
    select o1 as ord2, o1.Customer as cu2, o2 as sub1
    from Order o1
    left join (
      select o0 as ord1, o0.Customer as cu1
      from Order o0
    ) o2 on o1.OrderId = o2.ord1.OrderId-1
  ) o3 on o.OrderId = o3.ord2.OrderId-1
  where o.OrderId = 10248
) o4 on o5.OrderId = o4.ord3.OrderId

This feature is a requirement in order to support the Include method on all databases when paging results. Sql IN operator does not work with composite keys and in some databases even for normal keys (e.g. MySql), so with this feature we can write the following query:

select o
from CompositeOrder o 
inner join (
  select id
  from CompositeOrder
  order by OrderId skip 2 take 2
) o2 on o.id = o2.id
left join fetch o.OrderLines

Known limitation:

  • Selecting a hql constructor inside a subquery is not supported

Also fixes #2092

}

subclassPropertyAliases[propName] = aliases;
Copy link
Contributor Author

@maca88 maca88 Sep 17, 2020

Choose a reason for hiding this comment

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

Now subclassPropertyAliases contains also component properties which are needed in order to select component properties from a subquery.

@bahusoid

This comment has been minimized.

@maca88

This comment has been minimized.

@bahusoid

This comment has been minimized.

@bahusoid
Copy link
Member

And your alias related changes seem to fix issue reported here:
#2092

I see no duplicates in generated SQL

@maca88
Copy link
Contributor Author

maca88 commented Sep 26, 2020

It's not possible to add association join dependent on subquery join

With the last commit the issue is fixed.

Copy link
Member

@fredericDelaporte fredericDelaporte left a comment

Choose a reason for hiding this comment

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

I have not reviewed the SelectClause changes. I lack knowledge of how it works there.

src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.cs Outdated Show resolved Hide resolved
@bahusoid

This comment was marked as resolved.

@maca88

This comment was marked as resolved.

bahusoid
bahusoid previously approved these changes Oct 26, 2022
bahusoid
bahusoid previously approved these changes Oct 27, 2022
}

var node = (IASTNode) e;
if (processedElements.Add(fromElement))
Copy link
Member

Choose a reason for hiding this comment

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

@maca88, this causes #3489 regression.
The query is

insert into Enrolment (Course, Student)
  select e.Course, e.Student from Enrolment e

At the second column, the from is already added, causing the execution to go into the else and not rendering the second column.

In debug, forcing the execution to jump directly to RenderNonScalarIdentifiers (so, not adding again the from to combinedFromElements) allows the test to succeed.

But surely the fix is not as simple as throwing away the else in all cases with something like:

if (processedElements.Add(fromElement))
{
	combinedFromElements.Add(fromElement);
}
RenderNonScalarIdentifiers(fromElement, inheritedExpressions.ContainsKey(e) ? null : e, appender);

Copy link
Member

@fredericDelaporte fredericDelaporte Mar 17, 2024

Choose a reason for hiding this comment

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

Doing that change seems to break only HqlDuplicateEntitySelectionSubQuery which looks like testing invalid cases, containing duplicated selection of entities. Why should we support theses cases?

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

Successfully merging this pull request may close these issues.

Projection and join fetch in hql leads to duplicated column aliases
4 participants