Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3702a71

Browse files
committed
Note: this will still lead to the UnitOfWork#getSingleIdentifierValue() still being
called when not specifying the type of a DQL parameter being bound via `Doctrine\ORM\Query#setParameter()`: ```php $query->setParameter('foo', $theValue, $theType); ``` A full parameter bind is required in order to gain back performance: ```php $query->setParameter('foo', $theValue, $theType); ``` This is up for discussion with patch reviewers.
1 parent 960a437 commit 3702a71

4 files changed

Lines changed: 63 additions & 23 deletions

File tree

lib/Doctrine/ORM/AbstractQuery.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ abstract class AbstractQuery
7272
/**
7373
* The parameter map of this query.
7474
*
75-
* @var \Doctrine\Common\Collections\ArrayCollection
75+
* @var ArrayCollection|Parameter[]
7676
*/
7777
protected $parameters;
7878

@@ -306,7 +306,7 @@ public function free()
306306
/**
307307
* Get all defined parameters.
308308
*
309-
* @return \Doctrine\Common\Collections\ArrayCollection The defined query parameters.
309+
* @return ArrayCollection The defined query parameters.
310310
*/
311311
public function getParameters()
312312
{
@@ -336,7 +336,7 @@ function (Query\Parameter $parameter) use ($key) : bool {
336336
/**
337337
* Sets a collection of query parameters.
338338
*
339-
* @param \Doctrine\Common\Collections\ArrayCollection|array $parameters
339+
* @param ArrayCollection|array $parameters
340340
*
341341
* @return static This query instance.
342342
*/

lib/Doctrine/ORM/Query.php

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,18 @@
1919

2020
namespace Doctrine\ORM;
2121

22+
use Doctrine\Common\Collections\ArrayCollection;
2223
use Doctrine\DBAL\LockMode;
24+
use Doctrine\ORM\Mapping\ClassMetadata;
2325
use Doctrine\ORM\Query\Exec\AbstractSqlExecutor;
26+
use Doctrine\ORM\Query\Parameter;
27+
use Doctrine\ORM\Query\ParameterTypeInferer;
2428
use Doctrine\ORM\Query\Parser;
2529
use Doctrine\ORM\Query\ParserResult;
2630
use Doctrine\ORM\Query\QueryException;
27-
use Doctrine\ORM\Mapping\ClassMetadata;
28-
use Doctrine\ORM\Query\ParameterTypeInferer;
29-
use Doctrine\Common\Collections\ArrayCollection;
3031
use Doctrine\ORM\Utility\HierarchyDiscriminatorResolver;
32+
use function array_keys;
33+
use function assert;
3134

3235
/**
3336
* A Query object represents a DQL query.
@@ -387,26 +390,13 @@ private function processParameterMappings($paramMappings)
387390
$types = [];
388391

389392
foreach ($this->parameters as $parameter) {
390-
$key = $parameter->getName();
391-
$value = $parameter->getValue();
392-
$rsm = $this->getResultSetMapping();
393+
$key = $parameter->getName();
393394

394395
if ( ! isset($paramMappings[$key])) {
395396
throw QueryException::unknownParameter($key);
396397
}
397398

398-
if (isset($rsm->metadataParameterMapping[$key]) && $value instanceof ClassMetadata) {
399-
$value = $value->getMetadataValue($rsm->metadataParameterMapping[$key]);
400-
}
401-
402-
if (isset($rsm->discriminatorParameters[$key]) && $value instanceof ClassMetadata) {
403-
$value = array_keys(HierarchyDiscriminatorResolver::resolveDiscriminatorsForClass($value, $this->_em));
404-
}
405-
406-
$value = $this->processParameterValue($value);
407-
$type = ($parameter->getValue() === $value)
408-
? $parameter->getType()
409-
: ParameterTypeInferer::inferType($value);
399+
[$value, $type] = $this->resolveParameterValue($parameter);
410400

411401
foreach ($paramMappings[$key] as $position) {
412402
$types[$position] = $type;
@@ -439,6 +429,38 @@ private function processParameterMappings($paramMappings)
439429
return [$sqlParams, $types];
440430
}
441431

432+
/** @return mixed[] tuple of (value, type) */
433+
private function resolveParameterValue(Parameter $parameter) : array
434+
{
435+
if ($parameter->typeWasSpecified()) {
436+
return [$parameter->getValue(), $parameter->getType()];
437+
}
438+
439+
$key = $parameter->getName();
440+
$originalValue = $parameter->getValue();
441+
$value = $originalValue;
442+
$rsm = $this->getResultSetMapping();
443+
444+
assert($rsm !== null);
445+
446+
if ($value instanceof ClassMetadata && isset($rsm->metadataParameterMapping[$key])) {
447+
$value = $value->getMetadataValue($rsm->metadataParameterMapping[$key]);
448+
}
449+
450+
if ($value instanceof ClassMetadata && isset($rsm->discriminatorParameters[$key])) {
451+
$value = array_keys(HierarchyDiscriminatorResolver::resolveDiscriminatorsForClass($value, $this->_em));
452+
}
453+
454+
$processedValue = $this->processParameterValue($value);
455+
456+
return [
457+
$processedValue,
458+
$originalValue === $processedValue
459+
? $parameter->getType()
460+
: ParameterTypeInferer::inferType($processedValue),
461+
];
462+
}
463+
442464
/**
443465
* Defines a cache driver to be used for caching queries.
444466
*

lib/Doctrine/ORM/Query/Parameter.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
namespace Doctrine\ORM\Query;
2121

22+
use function trim;
23+
2224
/**
2325
* Defines a Query Parameter.
2426
*
@@ -49,6 +51,13 @@ class Parameter
4951
*/
5052
private $type;
5153

54+
/**
55+
* Whether the parameter type was explicitly specified or not
56+
*
57+
* @var bool
58+
*/
59+
private $typeSpecified;
60+
5261
/**
5362
* Constructor.
5463
*
@@ -58,7 +67,8 @@ class Parameter
5867
*/
5968
public function __construct($name, $value, $type = null)
6069
{
61-
$this->name = trim($name, ':');
70+
$this->name = trim($name, ':');
71+
$this->typeSpecified = $type !== null;
6272

6373
$this->setValue($value, $type);
6474
}
@@ -104,4 +114,9 @@ public function setValue($value, $type = null)
104114
$this->value = $value;
105115
$this->type = $type ?: ParameterTypeInferer::inferType($value);
106116
}
117+
118+
public function typeWasSpecified() : bool
119+
{
120+
return $this->typeSpecified;
121+
}
107122
}

tests/Doctrine/Tests/ORM/QueryBuilderTest.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -609,8 +609,11 @@ public function testSetParameter()
609609
->setParameter('id', 1);
610610

611611
$parameter = new Parameter('id', 1, ParameterTypeInferer::inferType(1));
612+
$inferred = $qb->getParameter('id');
612613

613-
$this->assertEquals($parameter, $qb->getParameter('id'));
614+
self::assertSame($parameter->getValue(), $inferred->getValue());
615+
self::assertSame($parameter->getType(), $inferred->getType());
616+
self::assertFalse($inferred->typeWasSpecified());
614617
}
615618

616619
public function testSetParameters()

0 commit comments

Comments
 (0)