Gummy
Gummy

Reputation: 164

Doctrine Conditional joins

I'm trying to figure out how to achieve conditional joins in doctrine.

I have an entity A with two fields, let's call them b (referencing a single Bobject) and c (referencing a single C object) respectively.

/**
* @Entity
**/
class A
{
    /** @ManyToOne(targetEntity="B") **/
    protected $b;
    /** @OneToOne(targetEntity="C") **/
    protected $c;
}

I want to write a DQL query which is going to perform an INNER JOIN on $b ONLY if $b is not null, and if $b is null the INNER JOIN should be applied to$c instead (if $c is not null too).

I tried combining INNER JOINS with WITH clauses checking for null values, but this doesn't work obviously.

SELECT a FROM model\entity\A a
INNER JOIN a.b ab WITH ab IS NOT NULL INNER JOIN ab.d abd (...)
INNER JOIN a.c ac WITH ac IS NOT NULL (...)

I also tried combining LEFT JOINS without success.

Long story short, here's the kind of DQL I'd like to obtain :

SELECT a FROM model\entity\A a
IF a.b IS NOT NULL INNER JOIN a.b ab WITH (...)
IF a.b IS NULL INNER JOIN a.c ac WITH (...)

I'll admit I don't even know if that kind of behaviour is achievable. I think it would be easier to split this into two distinct queries, one joining on $b and the other joining on $c then merging the results myself, but I'd really like to find a single-query solution (provided there is any).

Thanks for reading, and for any eventual help.

Cheers!

Upvotes: 2

Views: 2479

Answers (2)

Gummy
Gummy

Reputation: 164

Alternative solution found

So I couldn't find a solution while working with conditions directly in the JOIN statements. However, I decided to join all the entities I needed, and perform the condition checks in a classic WHERE statement.

If anyone runs into the same kind of issue, here's how I solved this :

Doesn't work :

SELECT a FROM model\entity\A a
LEFT JOIN a.b ab WITH ab IS NOT NULL INNER JOIN ab.d abd (...)
LEFT JOIN a.c ac WITH ac IS NOT NULL (...)

Works :

SELECT a FROM model\entity\A a
LEFT JOIN a.b ab
LEFT JOIN ab.d abd
LEFT JOIN a.c ac
WHERE ((ab IS NOT NULL AND (...)) OR (ac IS NOT NULL AND (...))) AND (...)

Thanks @Balmipour for telling me how to close this topic.

Upvotes: 1

Mihai Stancu
Mihai Stancu

Reputation: 16107

What you are describing is not possible in SQL, there is no concept of conditional joins because the structure of the result set must be consistent.

DQL only enhances SQL in the respect of ORM mapping not in the respect of adding features not present in SQL. On the contrairy DQL does not support SQL features not present in the SQL standards or which have no common ground between the major SQL RDBMS vendors -- i.e.: which are not supported by most vendors or have no equivalents in most vendors.

You can however build some PHP logic to help you with that; for example you can use the Doctrine QueryBuilder to build the query based on PHP-level if conditions evaluated using pre-fetched PHP-level data.

For example you could run a couple of DQL queries to pre-fetch the IDs from the a.b IS NULL group and the a.b IS NOT GROUP (separately) and then continue with one or more queries fetching the necessary data based on those IDs.

Upvotes: 1

Related Questions