From 6cb5a9c50a3143dfa60088e5799b9a2625b57966 Mon Sep 17 00:00:00 2001 From: Michael Moravec Date: Fri, 24 Nov 2017 02:22:07 +0100 Subject: [PATCH] Fix parameter name comparison in AbstractQuery#setParameter() with different types --- lib/Doctrine/ORM/AbstractQuery.php | 23 +++---- tests/Doctrine/Tests/ORM/Query/QueryTest.php | 63 ++++++++++++++++++++ 2 files changed, 71 insertions(+), 15 deletions(-) diff --git a/lib/Doctrine/ORM/AbstractQuery.php b/lib/Doctrine/ORM/AbstractQuery.php index ba013bbbb..10af39053 100644 --- a/lib/Doctrine/ORM/AbstractQuery.php +++ b/lib/Doctrine/ORM/AbstractQuery.php @@ -321,14 +321,14 @@ abstract class AbstractQuery public function getParameter($key) { $filteredParameters = $this->parameters->filter( - function ($parameter) use ($key) - { - // Must not be identical because of string to integer conversion - return ($key == $parameter->getName()); + function (Query\Parameter $parameter) use ($key) : bool { + $parameterName = $parameter->getName(); + + return $key === $parameterName || (string) $key === (string) $parameterName; } ); - return count($filteredParameters) ? $filteredParameters->first() : null; + return ! $filteredParameters->isEmpty() ? $filteredParameters->first() : null; } /** @@ -369,17 +369,10 @@ abstract class AbstractQuery */ public function setParameter($key, $value, $type = null) { - $filteredParameters = $this->parameters->filter( - function ($parameter) use ($key) - { - // Must not be identical because of string to integer conversion - return ($key == $parameter->getName()); - } - ); + $existingParameter = $this->getParameter($key); - if (count($filteredParameters)) { - $parameter = $filteredParameters->first(); - $parameter->setValue($value, $type); + if ($existingParameter !== null) { + $existingParameter->setValue($value, $type); return $this; } diff --git a/tests/Doctrine/Tests/ORM/Query/QueryTest.php b/tests/Doctrine/Tests/ORM/Query/QueryTest.php index 5a2a295fe..354586f15 100644 --- a/tests/Doctrine/Tests/ORM/Query/QueryTest.php +++ b/tests/Doctrine/Tests/ORM/Query/QueryTest.php @@ -12,6 +12,7 @@ use Doctrine\ORM\Query\QueryException; use Doctrine\Tests\Mocks\DriverConnectionMock; use Doctrine\Tests\Mocks\StatementArrayMock; use Doctrine\Tests\Models\CMS\CmsAddress; +use Doctrine\Tests\Models\CMS\CmsUser; use Doctrine\Tests\OrmTestCase; class QueryTest extends OrmTestCase @@ -303,4 +304,66 @@ class QueryTest extends OrmTestCase $this->expectExceptionMessage('Subquery'); $query->getSQL(); } + + /** + * @group 6699 + */ + public function testGetParameterTypeJuggling() : void + { + $query = $this->_em->createQuery('select u from ' . CmsUser::class . ' u where u.id = ?0'); + + $query->setParameter(0, 0); + + self::assertCount(1, $query->getParameters()); + self::assertSame(0, $query->getParameter(0)->getValue()); + self::assertSame(0, $query->getParameter('0')->getValue()); + } + + /** + * @group 6699 + */ + public function testSetParameterWithNameZeroIsNotOverridden() : void + { + $query = $this->_em->createQuery('select u from ' . CmsUser::class . ' u where u.id != ?0 and u.username = :name'); + + $query->setParameter(0, 0); + $query->setParameter('name', 'Doctrine'); + + self::assertCount(2, $query->getParameters()); + self::assertSame(0, $query->getParameter('0')->getValue()); + self::assertSame('Doctrine', $query->getParameter('name')->getValue()); + } + + /** + * @group 6699 + */ + public function testSetParameterWithNameZeroDoesNotOverrideAnotherParameter() : void + { + $query = $this->_em->createQuery('select u from ' . CmsUser::class . ' u where u.id != ?0 and u.username = :name'); + + $query->setParameter('name', 'Doctrine'); + $query->setParameter(0, 0); + + self::assertCount(2, $query->getParameters()); + self::assertSame(0, $query->getParameter(0)->getValue()); + self::assertSame('Doctrine', $query->getParameter('name')->getValue()); + } + + /** + * @group 6699 + */ + public function testSetParameterWithTypeJugglingWorks() : void + { + $query = $this->_em->createQuery('select u from ' . CmsUser::class . ' u where u.id != ?0 and u.username = :name'); + + $query->setParameter('0', 1); + $query->setParameter('name', 'Doctrine'); + $query->setParameter(0, 2); + $query->setParameter('0', 3); + + self::assertCount(2, $query->getParameters()); + self::assertSame(3, $query->getParameter(0)->getValue()); + self::assertSame(3, $query->getParameter('0')->getValue()); + self::assertSame('Doctrine', $query->getParameter('name')->getValue()); + } }