[hibernate-issues] [Hibernate-JIRA] Commented: (HHH-5352) Misleading replacement of commas with cross joins

Patras Vlad (JIRA) noreply at atlassian.com
Tue Jan 11 06:07:05 EST 2011


    [ http://opensource.atlassian.com/projects/hibernate/browse/HHH-5352?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=39566#action_39566 ] 

Patras Vlad commented on HHH-5352:
----------------------------------

Yes, it still an issue in 3.6.0

This issue is probably due to the not so obvious difference between comma and cross join SQL operators (as of SQL-99 standard).
On many forums and even books it's stated that they are functionally equivalent and it's just a matter of preference or what the DBE supports.
But they are NOT equivalent, for example consider the following SQL:
{code}
CREATE TABLE a (a INT);
CREATE TABLE b (b INT);
CREATE TABLE c (c INT);

INSERT INTO a VALUES (1);
INSERT INTO b VALUES (1);
INSERT INTO c VALUES (NULL);

-- Q1:
SELECT * FROM a ,          b RIGHT JOIN c on b.b = c.c;
-- Q2:
SELECT * FROM a CROSS JOIN b RIGHT JOIN c on b.b = c.c;
{code}
When running the above SQL in an SQL-99 compliant DBE (such as MySQL 5 or MS SQL Server 2005), Q1 and Q2 will return different results (Q1> 1 null null, Q2> null null null). The only difference between Q1 and Q2 is comma being replaced with CROSS JOIN, thus the two operators are not equivalent.

>From the hibernate source code:
{noformat:title=org.hibernate.dialect.Dialect.java}
	/**
	 * Get the separator to use for defining cross joins when translating HQL queries.
	 * <p/>
	 * Typically this will be either [<tt> cross join </tt>] or [<tt>, </tt>]
	 * <p/>
	 * Note that the spaces are important!
	 *
	 * @return
	 */
	public String getCrossJoinSeparator() {
		return " cross join ";
	}
{noformat}
It is obvious that the developer is not aware that CROSS JOIN is different from comma. First, the method is named getCrossJoinSeparator even though it refers to what a comma in HQL is going to be replaced with,  and then there is the comment that says "Typically this will be either <tt> cross join </tt> or <tt>, </tt>".

This functionality was implemented to fix HHH-1480. But that is not an actual fix, it's a hack.
Basicly HHH-1480 says "JOIN and comma have different precedence in SQL but they have the same precedence in HQL".
Instead of fixing the problem, the solution was "Oh, we will just change the meaning of comma in HQL to be a CROSS JOIN so it will have the same precedence as other JOINs".
Changing the meaning of comma changes the results returned by HQL queries. All this happens silently, it's not even specified in the documentation. If an application does not have comprehensive unit testing this is likely to go by unnoticed.

> Misleading replacement of commas with cross joins
> -------------------------------------------------
>
>                 Key: HHH-5352
>                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-5352
>             Project: Hibernate Core
>          Issue Type: Bug
>    Affects Versions: 3.5.0-Beta-2, 3.5.0-Beta-3, 3.5.0-Beta-4, 3.5.0-CR-1, 3.5.0-CR-2, 3.5.0-Final, 3.5.1, 3.5.2, 3.5.3
>         Environment: Hibernate 3.5.3
> Ms SQL Server 2005
>            Reporter: Patras Vlad
>
>   There was a new feature implemented in 3.5.0-Beta-2: HHH-1480, as a result, for many dialects, the comma operator "," was replaced with "cross join". As it's already obvious from the feature's description, this changes join precedence. If the query contains outer joins (left or right) this replacement changes the results (because outer join precedence is important).
>   This might not be interpreted as a bug if you know what SQL operator will be generated when you place a comma in HQL, but it's misleading if you don't. A HQL query like:
> {noformat}select a from A a, B left join B.c c{noformat} 
> is not equivalent with the SQL query:
> {noformat}select a.* from A.a, B b left join C c on b.cid = c.id{noformat} 
> because the actual SQL query is:
> {noformat}select a.* from A.a cross join B b left join C c on b.cid = c.id{noformat}
> The first SQL query would make a left join on B and C and then a cross join with the result and A (and this is what we should expect). The second SQL query makes a cross join on A and B and then a left join with the result and C (this is not expected since we had a comma in HQL).
> I understand the issues presented in HHH-1480, but they should be expected, i.e. a developer SHOULD expect a faliure from a query like 
> {noformat}select a from A a, B b join a.c C{noformat}
> because "a" is not visible in the join. Hibernate should not use a cross join behind the scenes to allow such a query at the expense of providing misleading results for others.
> Maybe turn this into a feature/improvement or add another to allow explicit comma or croos join in HQL, or support parenthesis in HQL.
> The only workaround I can see for now is to re-order the query like this:
> {noformat}select a from B left join B.c c, A a{noformat} 

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        


More information about the hibernate-issues mailing list