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

[DDC-2235] Fix for using a LEFT JOIN onto an entity with single table inheritance #656

Closed
wants to merge 7 commits into from

Conversation

tarnfeld
Copy link

Possible fix for the bug DDC-2235. I'd love to hear some opinions on whether this is the right way to go about this issue. I'm not particularly familiar with the internals of doctrine so there may be a better solution.


The issue is when using DQL to perform a left join on an entity using single table inheritance, doctrine tries to insert an IN() predicate into the WHERE clause for all of the discriminator values. That makes sense and is valid, so it would be wrong to remove that behaviour.

However when using a left join having an IN() in the main where clause makes the LEFT JOIN pretty much useless, as it implicitly creates a WHERE NOT NULL clause. This commit attempts to fix that by including an OR IS NULL in the query if the join is a LEFT JOIN.

I've added some regression tests to ensure this bug never creeps back in. They fail on master (highlighting the bug) and pass after these commits have been applied. I've also included a couple of other queries as tests to be sure only this one case has been affected.

The issue is when using DQL to perform a left join on an entity using single
table inheritance, doctrine tries to insert an `IN()` predicate into the `WHERE`
clause for all of the discriminator values. That makes sense and is valid, so
it would be wrong to remove that behaviour.

However when using a *left* join having an `IN()` in the main where clause makes
the `LEFT JOIN` pretty much useless, as it implicitly creates a `WHERE NOT NULL`
clause. This commit attempts to fix that by including an `OR IS NULL` in the
query if the join is a `LEFT JOIN`.
@@ -1026,6 +1040,10 @@ public function walkJoin($join)
? ' LEFT JOIN '
: ' INNER JOIN ';

if ($joinType == AST\Join::JOIN_TYPE_LEFT) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use strict comparison and yoda conditionals

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@Ocramius
Copy link
Member

By the way, this doesn't seem to solve the problem, rather than patching up the symptoms... Shouldn't all the IN be applied in the ON clause instead?

@tarnfeld
Copy link
Author

I'd much prefer that, but not quite sure where the other parts of the ON clause are generated, and whether its best to just arbitrarily put an AND IN() on the end of that string, or if there is a better way to go about it.

If you could point me in the right direction I'll gladly implement it. :)

@tarnfeld
Copy link
Author

Got it - will push a new commit with that implemented shortly.

@tarnfeld
Copy link
Author

@Ocramius updated

@@ -437,7 +437,7 @@ private function _generateDiscriminatorColumnConditionSQL(array $dqlAliases)
}

$sqlParts[] = (($this->useSqlTableAliases) ? $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.' : '')
. $class->discriminatorColumn['name'] . ' IN (' . implode(', ', $values) . ')';
. $class->discriminatorColumn['name'] . ' IN (' . implode(', ', $values) . ')';
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gah, will fix this whitespace.

@tarnfeld
Copy link
Author

@Ocramius Any news on this being reviewed again / merged into master?

@eugene1g
Copy link

The patch worked for my use-case (similar situation, left-joining a model with a discriminator column)

@Ocramius
Copy link
Member

@tarnfeld merges of such major changes are not up to me - I generally agree with what you have implemented here though

. $condExprConjunction . '(' . $this->walkConditionalExpression($join->conditionalExpression) . ')';

$discrSql = $this->_generateDiscriminatorColumnConditionSQL(array($joinAlias));
if ( ! empty($discrSql)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing newline before this line

@tarnfeld
Copy link
Author

@Ocramius Thanks for the heads up, i've pushed a fix for the new line.

@guilhermeblanco
Copy link
Member

I'm working on this issue.

@guilhermeblanco guilhermeblanco mentioned this pull request Aug 16, 2013
@guilhermeblanco
Copy link
Member

I replaced this PR with a more in depth solution as of #758
I reused the tests available here but also fixed the filter support which was missing on this patch.

@tarnfeld
Copy link
Author

Nice one, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants