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
Handle Empty Array for IN and NOT IN queries. #8035
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,8 @@ | |
|
||
namespace Doctrine\ORM\Query\Expr; | ||
|
||
use function count; | ||
|
||
/** | ||
* Expression class for generating DQL functions. | ||
* | ||
|
@@ -73,6 +75,10 @@ public function getArguments() | |
*/ | ||
public function __toString() | ||
{ | ||
if (count($this->arguments) === 0) { | ||
return $this->name . '(NULL)'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wait so There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that's what I discovered 😅 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This makes it a bit scary… touching such a generic method looks like it could have unforeseen repercussions. |
||
} | ||
|
||
return $this->name . '(' . implode(', ', $this->arguments) . ')'; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -282,6 +282,11 @@ public function testInLiteralExpr() | |
$this->assertEquals("u.type IN('foo', 'bar')", (string) $this->_expr->in('u.type', ['foo', 'bar'])); | ||
} | ||
|
||
public function testInExprForEmptyArray() | ||
{ | ||
self::assertEquals('u.id IN(NULL)', (string) $this->_expr->in('u.id', [])); | ||
} | ||
|
||
public function testNotInExpr() | ||
{ | ||
$this->assertEquals('u.id NOT IN(1, 2, 3)', (string) $this->_expr->notIn('u.id', [1, 2, 3])); | ||
|
@@ -292,6 +297,11 @@ public function testNotInLiteralExpr() | |
$this->assertEquals("u.type NOT IN('foo', 'bar')", (string) $this->_expr->notIn('u.type', ['foo', 'bar'])); | ||
} | ||
|
||
public function testNotInExprForEmptyArray() | ||
{ | ||
self::assertEquals('u.id NOT IN(NULL)', (string) $this->_expr->notIn('u.id', [])); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
https://dbfiddle.uk/?rdbms=sqlite_3.8&fiddle=0097a9450b4e56c142e64a480b745614 this contradicts with your expectations described in your issue #8033 (comment) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I know. It's still an improvement since
And in the next comment #8033 (comment), I explained that
Is actually translated as So my PR make the behaviour of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can improve the behaviour of the NOT IN query with an empty array, but It'll need a lot a more code changes and some discussions, so I recommend to split this from this PR, which was only looking for more consistency. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you want to split it, then you'll have to remove the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I disagree. Actually if you write
There is no exception and this is translated as But if you write directly
You get an exception. But there is absolutely no reason to behave differently from the first case. So it's still an improvement to have a consistent behaviour for I improve both the I don't know what I have to change to completely supports the NOT IN case and if it's possible. It should handle correctly the case
And this seems for me like a lot of work/rework. Is this PR perfect and fixing everything ? No |
||
} | ||
|
||
public function testAndxOrxExpr() | ||
{ | ||
$andExpr = $this->_expr->andX(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wouldn't this return all elements where the value is null for nullable columns? This seems wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@beberlei No,
Return always 0 row. I tried it multiple times.
foo IN (A, B)
meanfoo = A or foo = B
foo IN (NULL)
meanfoo = NULL
foo = NULL
always returns no result, instead offoo IS NULL
.And as explained here: #8033 (comment), this is already the query created when using
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK
NULL
is handled that way in all commonly known databases like e.g. PostgreSQL, MySQL, SQLite...https://dbfiddle.uk/?rdbms=sqlite_3.8&fiddle=ac349cc3ca597516e307d690e7f19d90
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I saw this nice comic on Twitter about this the other day :)
— 🔎Julia Evans🔍 (
@b0rk
) October 17, 2019