From f2f571e4aba340bfb07ad2296d1e4a1ab82d0c35 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 3 Apr 2014 16:01:30 +0200 Subject: [PATCH 1/5] DDC-3065 - failing test - IN()-alike criteria should support NULL search values --- .../ORM/Functional/EntityRepositoryTest.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php b/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php index 502eda0ec..3286b0ff1 100644 --- a/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php @@ -928,5 +928,23 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase $repository = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser'); $repository->find(array('username = ?; DELETE FROM cms_users; SELECT 1 WHERE 1' => 'test', 'id' => 1)); } + + /** + * @group DDC-3056 + */ + public function testFindByNullValueInInCondition() + { + $user = new CmsUser(); + + $user->username = 'ocramius'; + $user->name = 'Marco'; + + $this->_em->persist($user); + $this->_em->flush(); + + $users = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser')->findBy(array('email' => array(null))); + + $this->assertCount(1, $users); + } } From f54d6157f44ea1cdecede9bcd3f48cc5cb04b065 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 3 Apr 2014 16:03:56 +0200 Subject: [PATCH 2/5] DDC-3065 - hardening test - should support multiple values in IN(), also NULL ones --- .../Tests/ORM/Functional/EntityRepositoryTest.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php b/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php index 3286b0ff1..f33feb2bc 100644 --- a/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php @@ -942,9 +942,18 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->_em->persist($user); $this->_em->flush(); - $users = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser')->findBy(array('email' => array(null))); + $users = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser')->findBy(array('status' => array(null))); $this->assertCount(1, $users); + $this->assertSame($user, reset($users)); + + $users = $this + ->_em + ->getRepository('Doctrine\Tests\Models\CMS\CmsUser') + ->findBy(array('status' => array('foo', null))); + + $this->assertCount(1, $users); + $this->assertSame($user, reset($users)); } } From eb6498544f7c0689ea3f146d21b7b8710ba97709 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 3 Apr 2014 16:12:34 +0200 Subject: [PATCH 3/5] DDC-3065 - splitting tests and checking multiple values support --- .../ORM/Functional/EntityRepositoryTest.php | 69 +++++++++++++++++-- 1 file changed, 63 insertions(+), 6 deletions(-) diff --git a/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php b/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php index f33feb2bc..f20ba88e5 100644 --- a/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php @@ -934,18 +934,44 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase */ public function testFindByNullValueInInCondition() { - $user = new CmsUser(); + $user1 = new CmsUser(); + $user2 = new CmsUser(); - $user->username = 'ocramius'; - $user->name = 'Marco'; + $user1->username = 'ocramius'; + $user1->name = 'Marco'; + $user2->status = null; + $user2->username = 'deeky666'; + $user2->name = 'Steve'; + $user2->status = 'dbal maintainer'; - $this->_em->persist($user); + $this->_em->persist($user1); + $this->_em->persist($user2); $this->_em->flush(); $users = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser')->findBy(array('status' => array(null))); $this->assertCount(1, $users); - $this->assertSame($user, reset($users)); + $this->assertSame($user1, reset($users)); + } + + /** + * @group DDC-3056 + */ + public function testFindByNullValueInMultipleInCriteriaValues() + { + $user1 = new CmsUser(); + $user2 = new CmsUser(); + + $user1->username = 'ocramius'; + $user1->name = 'Marco'; + $user2->status = null; + $user2->username = 'deeky666'; + $user2->name = 'Steve'; + $user2->status = 'dbal maintainer'; + + $this->_em->persist($user1); + $this->_em->persist($user2); + $this->_em->flush(); $users = $this ->_em @@ -953,7 +979,38 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase ->findBy(array('status' => array('foo', null))); $this->assertCount(1, $users); - $this->assertSame($user, reset($users)); + $this->assertSame($user1, reset($users)); + } + + /** + * @group DDC-3056 + */ + public function testFindMultipleByNullValueInMultipleInCriteriaValues() + { + $user1 = new CmsUser(); + $user2 = new CmsUser(); + + $user1->username = 'ocramius'; + $user1->name = 'Marco'; + $user2->status = null; + $user2->username = 'deeky666'; + $user2->name = 'Steve'; + $user2->status = 'dbal maintainer'; + + $this->_em->persist($user1); + $this->_em->persist($user2); + $this->_em->flush(); + + $users = $this + ->_em + ->getRepository('Doctrine\Tests\Models\CMS\CmsUser') + ->findBy(array('status' => array('dbal maintainer', null))); + + $this->assertCount(2, $users); + + foreach ($users as $user) { + $this->assertTrue(in_array($user, array($user1, $user2))); + } } } From a8b96803a4d8e994129aaa411c81661c3da16e2a Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 3 Apr 2014 17:17:24 +0200 Subject: [PATCH 4/5] DDC-3065 - persister tests for criteria containing `NULL` values in `IN()` conditions --- .../BasicEntityPersisterTypeValueSqlTest.php | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/Doctrine/Tests/ORM/Persisters/BasicEntityPersisterTypeValueSqlTest.php b/tests/Doctrine/Tests/ORM/Persisters/BasicEntityPersisterTypeValueSqlTest.php index 668ff13a0..686f2ee18 100644 --- a/tests/Doctrine/Tests/ORM/Persisters/BasicEntityPersisterTypeValueSqlTest.php +++ b/tests/Doctrine/Tests/ORM/Persisters/BasicEntityPersisterTypeValueSqlTest.php @@ -13,9 +13,19 @@ require_once __DIR__ . '/../../TestInit.php'; class BasicEntityPersisterTypeValueSqlTest extends \Doctrine\Tests\OrmTestCase { + /** + * @var BasicEntityPersister + */ protected $_persister; + + /** + * @var \Doctrine\ORM\EntityManager + */ protected $_em; + /** + * {@inheritDoc} + */ protected function setUp() { parent::setUp(); @@ -110,4 +120,25 @@ class BasicEntityPersisterTypeValueSqlTest extends \Doctrine\Tests\OrmTestCase $statement = $this->_persister->getSelectConditionStatementSQL('test', null, array(), Comparison::NEQ); $this->assertEquals('test IS NOT NULL', $statement); } + + /** + * @group DDC-3056 + */ + public function testSelectConditionStatementWithMultipleValuesContainingNull() + { + $this->assertEquals( + '(t0.id IN (?) OR t0.id IS NULL)', + $this->_persister->getSelectConditionStatementSQL('id', array(null)) + ); + + $this->assertEquals( + '(t0.id IN (?) OR t0.id IS NULL)', + $this->_persister->getSelectConditionStatementSQL('id', array(null, 123)) + ); + + $this->assertEquals( + '(t0.id IN (?) OR t0.id IS NULL)', + $this->_persister->getSelectConditionStatementSQL('id', array(123, null)) + ); + } } From 733102b4a109c0bb8ca026b1dbbadaa9bb62ae70 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 3 Apr 2014 17:17:58 +0200 Subject: [PATCH 5/5] DDC-3065 - applying hotfix that allows `NULL` in `IN()` criteria --- lib/Doctrine/ORM/Persisters/BasicEntityPersister.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php index 6504a3ee0..6fc1f9966 100644 --- a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php +++ b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php @@ -1534,7 +1534,13 @@ class BasicEntityPersister implements EntityPersister } if (is_array($value)) { - return sprintf('%s IN (%s)' , $condition, $placeholder); + $in = sprintf('%s IN (%s)' , $condition, $placeholder); + + if (false !== array_search(null, $value, true)) { + return sprintf('(%s OR %s IS NULL)' , $in, $condition); + } + + return $in; } if ($value === null) {