Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 357843

Summary: A where clause on a sub-attribute (e.g. where emp.addr.name is not null) will change outer joins further up the hierarchy to inner joins
Product: z_Archived Reporter: Martin Marinschek <martin.marinschek>
Component: EclipselinkAssignee: Nobody - feel free to take it <nobody>
Status: RESOLVED INVALID QA Contact:
Severity: major    
Priority: P2 CC: jamesssss, tom.ware
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:

Description Martin Marinschek CLA 2011-09-15 13:15:24 EDT
Build Identifier: 2.2.1

This behaviour effectively makes building complex queries spanning multiple tables (where some are optionally joined in) impossible.

There is an easy fix to this - get rid of the result.doNotUseOuterJoin() statement below. I have tested the patch and it works for my environment. Note that in another issue, I also suggested to change super.get() to deriving the expression from the store, just as getAllowingNull does it.

In any case, it would be interesting to know what the reason for this doNotUseOuterJoin() is - I don't see any reason from a generated SQL perspective?

ObjectExpression:

    public Expression get(String attributeName, Vector arguments) {
        Expression operatorExpression = super.get(attributeName, arguments);
        if (operatorExpression != null) {
            return operatorExpression;
        }

        QueryKeyExpression result = derivedExpressionNamed(attributeName);
        result.doNotUseOuterJoin();
        return result;

    }

Reproducible: Always
Comment 1 Martin Marinschek CLA 2011-09-15 16:52:25 EDT
Let me rephrase my example, cause in the given form it does not make much sense:

a where clause including: (emp.addr.name = 'Max' or emp.addr.name is null)

would not work.

best regards,

Martin
Comment 2 Tom Ware CLA 2011-09-22 11:54:03 EDT
I assume your query is something like

select emp from Employee emp where emp.addr.name = 'Max' or emp.addr.name is null

Can it be rewritten as something like

select emp from Employee emp left join emp.addr a where a.name = 'Max' or a.name is null
Comment 3 Martin Marinschek CLA 2011-09-23 00:32:59 EDT
Hi Tom,

it is more complex than this - goes over two hierarchies. I don't find a nice example with employee which makes sense and spans two hierarchies, I'll try it with a query from our domain:

select wl from worklist wl left join wl.approval app left join app.approver apprv where (apprv.id is null or apprv.id = 'someId');

We of course have much more complex queries than this, spanning many more entities!

Whenever I do something like this, outer joins are converted to inner joins. Query hints don't help. Also when ordering on something on the second hierarchy level, outer joins are converted to inner joins.

All due to the code above. I really wonder why you guys are doing this?

best regards,

Martin
Comment 4 Tom Ware CLA 2011-09-23 10:00:42 EDT
Can you give me an example of some mappings that show the issue.

I have tried with a fairly simple example with Project - 1-1 -> Employee - 1-1 -> Address and this query:

select p from Project p left join p.teamLeader e left join e.address a where a.city = 'Ottawa'

I still get the outer joins.

FYI: the Expression.get() method is specifically designed to do a non-outer join. getAllowingNull() is the outer join equivalent (as you have mentioned)
Comment 5 Martin Marinschek CLA 2011-10-09 00:19:21 EDT
I will provide you with a test setup as soon as time permits - right now I am a bit in stress for a project delivery. It might as well be that it is not the where clause, but the order by which calls the get() and gets rid of the outer join.
Comment 6 Tom Ware CLA 2011-10-13 13:29:17 EDT
Setting target and priority.  See the following page for the meanings of these fields:

http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines

Community: Please vote for this bug if it is important to you.  Votes are one of the main criteria we use to determine which bugs to fix next.
Comment 7 James Sutherland CLA 2011-11-23 13:53:13 EST
The issue is that the user is doing,

Select e from Employee e left join e.address a where a.country = 'Canada' order by e.address.city

EclipseLink is correct in using an inner join for address in this case, as e.address requires an inner join by the JPQL spec.  The error is in the users JPQL, it should instead be,

Select e from Employee e left join e.address a where a.country = 'Canada' order by a.city

You must use the alias to ensure the outer join.
Comment 8 Eclipse Webmaster CLA 2022-06-09 10:30:37 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink