-
Notifications
You must be signed in to change notification settings - Fork 934
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
Use proper inner join in Linq instead of implicit join and where clauses #2037
Conversation
@@ -363,6 +363,11 @@ public HqlJoin Join(HqlExpression expression, HqlAlias @alias) | |||
return new HqlJoin(_factory, expression, @alias); | |||
} | |||
|
|||
public HqlInnerJoin InnerJoin(HqlExpression expression, HqlAlias @alias) | |||
{ | |||
return new HqlInnerJoin(_factory, expression, @alias); |
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.
Unfortunately new join feature does not support implicit join types, so have to be explicit.
The description of #1128 is vague, so this change will make that issue obsolete. Technically the previous behaviour is correct despite being sub-optimal. |
dbc4485
to
40bd25e
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Somehow. Dlinq9 test: var actual =
(from o in db.Orders
from p in db.Products
join d in db.OrderLines
on new {o.OrderId, p.ProductId} equals new {d.Order.OrderId, d.Product.ProductId}
into details
from d in details
select new {o.OrderId, p.ProductId, d.UnitPrice}).ToList(); Is generating following SQL: select
order0_.OrderId as col_0_0_,
product1_.ProductId as col_1_0_,
orderline2_.UnitPrice as col_2_0_
from
Orders order0_,
Products product1_
inner join OrderLines orderline2_
on (orderline2_.OrderId=order0_.OrderId and orderline2_.ProductId=product1_.ProductId) However I'm not sure how the SQL should look like. |
Shouldn't your change eliminate theta-style joins? |
Only second join in this query. |
Well from ordering standpoint (which #2031 is about) everything is correct. Isn't it? So if it throws it's something else.. |
It throws: "System.Data.SqlClient.SqlException : The multi-part identifier "order0_.OrderId" could not be bound." |
It seems SQL Server doesn't like such mix of theta-style joins and inner joins. If convert to bogus inner join it works: select
order0_.OrderId as col_0_0_,
product1_.ProductId as col_1_0_,
orderline2_.UnitPrice as col_2_0_
from
Orders order0_
inner join Products product1_ on 1=1
inner join OrderLines orderline2_
on (orderline2_.OrderId=order0_.OrderId and orderline2_.ProductId=product1_.ProductId) Maybe we should completely get rid of theta-style joins in Linq? |
What would be SQL for that query? |
SQL server is not alone there, actually. Postgres throws a similar exception:
|
Actually, these are called not "theta join" but "implicit join" |
This comment has been minimized.
This comment has been minimized.
I'm not sure it's a good fix. It surely breaks mix of implicit and right joins in hql - see https://hibernate.atlassian.net/browse/HHH-5352 |
There is still ordering issue with "cross join" fix for 'CrossJoinAndWithClause' :( IMHO this Cross join behavior should be configurable per query and be enabled by default only from linq as HHH-5352 is a valid concern. |
Did it work in 5.2? ;-) |
Actually yes. You can mix implicit join and right join on association in 5.2: select a, b, c
from a, b
right join b.c with .. This cross join fix breaks such queries |
Hm.. There is also interesting commit which might fix my right join issue. Though not sure.. |
b87f858
to
405a0d3
Compare
As I am trying to add support for left joins for Linq (#864) and this issue is related, I want to give my thoughts about this.
I do agree. We shouldn't use comma syntax for doing a join, as it is an old way to join tables and it is not flexible, a simple explanation why can be found in the mariadb documentation.
The query should look like this: select
order0_.OrderId as col_0_0_,
product1_.ProductId as col_1_0_,
orderline2_.UnitPrice as col_2_0_
from
Orders order0_
cross join Products product1_
inner join OrderLines orderline2_
on (orderline2_.OrderId=order0_.OrderId and orderline2_.ProductId=product1_.ProductId) Using a cross join allows us to reference the joined table in the later joins which is not possible when using the comma syntax.
I do agree, I think that we shouldn't port the "fix" from Hibernate that replaces comma joins with cross joins as already mentioned, it is not the same when additional joins are added afterwards.
The query in that test is not valid as the left join references the table that is not available due to the JOIN precedence rules in SQL-99. IMO we shouldn't try to fix such queries, I think it is the user responsibility to know what are the limitations when using the comma syntax for joining tables.
I don't think that we need to fix anything when the user mixes comma joins with right/left/inner joins, for the above query we should convert it to sql as it is, without trying to convert the comma joins into cross joins. |
Yes we figured it out in the issue discussion. See pretty much the same thoughts here #2031 (comment) Also I did realize that entity join implementation in hql that I ported from hibernate have some flaws when mixed with associations. If I remember correctly entity joins are simply appended to the end disregarding it's actual usage in HQL. See example here: #2031 (comment) P.S. Sorry I don't really have time to actively participate now. |
Is this PR still valid? Isn't this functionality already implemented in #2327? |
I don’t know now:) |
Yes it is, this PR can be closed. |
Closes #1128