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

Use proper inner join in Linq instead of implicit join and where clauses #2037

Closed
wants to merge 1 commit into from

Conversation

hazzik
Copy link
Member

@hazzik hazzik commented Mar 3, 2019

Closes #1128

@@ -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);
Copy link
Member Author

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.

@hazzik
Copy link
Member Author

hazzik commented Mar 3, 2019

The description of #1128 is vague, so this change will make that issue obsolete. Technically the previous behaviour is correct despite being sub-optimal.

@hazzik hazzik force-pushed the proper-inner-join branch from dbc4485 to 40bd25e Compare March 3, 2019 23:25
@hazzik

This comment has been minimized.

@bahusoid

This comment has been minimized.

@hazzik

This comment has been minimized.

@hazzik
Copy link
Member Author

hazzik commented Mar 4, 2019

So are you sure that this PR depends on this issue? As from my understanding existing tests shouldn't suffer from this issue.

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.

@bahusoid
Copy link
Member

bahusoid commented Mar 4, 2019

Shouldn't your change eliminate theta-style joins?

@hazzik
Copy link
Member Author

hazzik commented Mar 4, 2019

Shouldn't you change eliminate theta-style joins?

Only second join in this query.

@bahusoid
Copy link
Member

bahusoid commented Mar 4, 2019

Well from ordering standpoint (which #2031 is about) everything is correct. Isn't it? So if it throws it's something else..

@hazzik
Copy link
Member Author

hazzik commented Mar 4, 2019

It throws:

"System.Data.SqlClient.SqlException : The multi-part identifier "order0_.OrderId" could not be bound."

@bahusoid
Copy link
Member

bahusoid commented Mar 4, 2019

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?

@hazzik
Copy link
Member Author

hazzik commented Mar 4, 2019

Maybe we should completely get rid of theta-style joins in Linq?

What would be SQL for that query?

@hazzik
Copy link
Member Author

hazzik commented Mar 4, 2019

SQL server is not alone there, actually. Postgres throws a similar exception:

----> Npgsql.PostgresException : 42P01: invalid reference to FROM-clause entry for table "order0_"

@hazzik
Copy link
Member Author

hazzik commented Mar 4, 2019

Actually, these are called not "theta join" but "implicit join"

@bahusoid

This comment has been minimized.

@hazzik
Copy link
Member Author

hazzik commented Mar 4, 2019

Ok, found correct issue: HHH-1480 + HHH-11337

@bahusoid
Copy link
Member

bahusoid commented Mar 4, 2019

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

@bahusoid
Copy link
Member

bahusoid commented Mar 4, 2019

There is still ordering issue with "cross join" fix for 'CrossJoinAndWithClause' :(
And if you need I can provide failing RIGHT join test due to "cross join" fix which works on master.

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.

@hazzik
Copy link
Member Author

hazzik commented Mar 4, 2019

I can provide failing RIGHT join test due to "cross join" fix which works on master.

Did it work in 5.2? ;-)

@bahusoid
Copy link
Member

bahusoid commented Mar 4, 2019

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

@bahusoid
Copy link
Member

bahusoid commented Mar 4, 2019

Hm.. There is also interesting commit which might fix my right join issue. Though not sure..

@hazzik hazzik force-pushed the proper-inner-join branch from b87f858 to 405a0d3 Compare April 15, 2019 02:19
@nhibernate nhibernate deleted a comment from autorebase bot Jun 14, 2019
@maca88
Copy link
Contributor

maca88 commented Mar 8, 2020

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.

Maybe we should completely get rid of theta-style joins in Linq?

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.

What would be SQL for that query?

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'm not sure it's a good fix. It surely breaks mix of implicit and right joins in hql

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.

There is still ordering issue with "cross join" fix for 'CrossJoinAndWithClause'

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.

There is also interesting commit which might fix my right join issue

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.

@bahusoid
Copy link
Member

bahusoid commented Mar 9, 2020

The query in that test is not valid

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.

@bahusoid
Copy link
Member

Is this PR still valid? Isn't this functionality already implemented in #2327?

@hazzik
Copy link
Member Author

hazzik commented Mar 22, 2020

I don’t know now:)

@maca88
Copy link
Contributor

maca88 commented Mar 22, 2020

Isn't this functionality already implemented in #2327?

Yes it is, this PR can be closed.

@hazzik hazzik closed this Mar 22, 2020
@bahusoid bahusoid changed the title Use proper inner join in Linq instead of cross-join and where clauses Use proper inner join in Linq instead of implicit join and where clauses Mar 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants