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.
This commit is contained in:
parent
960a437d46
commit
23af164d7a
@ -72,7 +72,7 @@ abstract class AbstractQuery
|
||||
/**
|
||||
* The parameter map of this query.
|
||||
*
|
||||
* @var \Doctrine\Common\Collections\ArrayCollection
|
||||
* @var ArrayCollection|Parameter[]
|
||||
*/
|
||||
protected $parameters;
|
||||
|
||||
@ -306,7 +306,7 @@ abstract class AbstractQuery
|
||||
/**
|
||||
* Get all defined parameters.
|
||||
*
|
||||
* @return \Doctrine\Common\Collections\ArrayCollection The defined query parameters.
|
||||
* @return ArrayCollection The defined query parameters.
|
||||
*/
|
||||
public function getParameters()
|
||||
{
|
||||
@ -336,7 +336,7 @@ abstract class AbstractQuery
|
||||
/**
|
||||
* Sets a collection of query parameters.
|
||||
*
|
||||
* @param \Doctrine\Common\Collections\ArrayCollection|array $parameters
|
||||
* @param ArrayCollection|mixed[] $parameters
|
||||
*
|
||||
* @return static This query instance.
|
||||
*/
|
||||
|
@ -19,15 +19,18 @@
|
||||
|
||||
namespace Doctrine\ORM;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\DBAL\LockMode;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Query\Exec\AbstractSqlExecutor;
|
||||
use Doctrine\ORM\Query\Parameter;
|
||||
use Doctrine\ORM\Query\ParameterTypeInferer;
|
||||
use Doctrine\ORM\Query\Parser;
|
||||
use Doctrine\ORM\Query\ParserResult;
|
||||
use Doctrine\ORM\Query\QueryException;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Query\ParameterTypeInferer;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\Utility\HierarchyDiscriminatorResolver;
|
||||
use function array_keys;
|
||||
use function assert;
|
||||
|
||||
/**
|
||||
* A Query object represents a DQL query.
|
||||
@ -387,26 +390,13 @@ final class Query extends AbstractQuery
|
||||
$types = [];
|
||||
|
||||
foreach ($this->parameters as $parameter) {
|
||||
$key = $parameter->getName();
|
||||
$value = $parameter->getValue();
|
||||
$rsm = $this->getResultSetMapping();
|
||||
$key = $parameter->getName();
|
||||
|
||||
if ( ! isset($paramMappings[$key])) {
|
||||
throw QueryException::unknownParameter($key);
|
||||
}
|
||||
|
||||
if (isset($rsm->metadataParameterMapping[$key]) && $value instanceof ClassMetadata) {
|
||||
$value = $value->getMetadataValue($rsm->metadataParameterMapping[$key]);
|
||||
}
|
||||
|
||||
if (isset($rsm->discriminatorParameters[$key]) && $value instanceof ClassMetadata) {
|
||||
$value = array_keys(HierarchyDiscriminatorResolver::resolveDiscriminatorsForClass($value, $this->_em));
|
||||
}
|
||||
|
||||
$value = $this->processParameterValue($value);
|
||||
$type = ($parameter->getValue() === $value)
|
||||
? $parameter->getType()
|
||||
: ParameterTypeInferer::inferType($value);
|
||||
[$value, $type] = $this->resolveParameterValue($parameter);
|
||||
|
||||
foreach ($paramMappings[$key] as $position) {
|
||||
$types[$position] = $type;
|
||||
@ -439,6 +429,38 @@ final class Query extends AbstractQuery
|
||||
return [$sqlParams, $types];
|
||||
}
|
||||
|
||||
/** @return mixed[] tuple of (value, type) */
|
||||
private function resolveParameterValue(Parameter $parameter) : array
|
||||
{
|
||||
if ($parameter->typeWasSpecified()) {
|
||||
return [$parameter->getValue(), $parameter->getType()];
|
||||
}
|
||||
|
||||
$key = $parameter->getName();
|
||||
$originalValue = $parameter->getValue();
|
||||
$value = $originalValue;
|
||||
$rsm = $this->getResultSetMapping();
|
||||
|
||||
assert($rsm !== null);
|
||||
|
||||
if ($value instanceof ClassMetadata && isset($rsm->metadataParameterMapping[$key])) {
|
||||
$value = $value->getMetadataValue($rsm->metadataParameterMapping[$key]);
|
||||
}
|
||||
|
||||
if ($value instanceof ClassMetadata && isset($rsm->discriminatorParameters[$key])) {
|
||||
$value = array_keys(HierarchyDiscriminatorResolver::resolveDiscriminatorsForClass($value, $this->_em));
|
||||
}
|
||||
|
||||
$processedValue = $this->processParameterValue($value);
|
||||
|
||||
return [
|
||||
$processedValue,
|
||||
$originalValue === $processedValue
|
||||
? $parameter->getType()
|
||||
: ParameterTypeInferer::inferType($processedValue),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a cache driver to be used for caching queries.
|
||||
*
|
||||
|
@ -19,6 +19,8 @@
|
||||
|
||||
namespace Doctrine\ORM\Query;
|
||||
|
||||
use function trim;
|
||||
|
||||
/**
|
||||
* Defines a Query Parameter.
|
||||
*
|
||||
@ -49,6 +51,13 @@ class Parameter
|
||||
*/
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* Whether the parameter type was explicitly specified or not
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $typeSpecified;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@ -58,7 +67,8 @@ class Parameter
|
||||
*/
|
||||
public function __construct($name, $value, $type = null)
|
||||
{
|
||||
$this->name = trim($name, ':');
|
||||
$this->name = trim($name, ':');
|
||||
$this->typeSpecified = $type !== null;
|
||||
|
||||
$this->setValue($value, $type);
|
||||
}
|
||||
@ -104,4 +114,9 @@ class Parameter
|
||||
$this->value = $value;
|
||||
$this->type = $type ?: ParameterTypeInferer::inferType($value);
|
||||
}
|
||||
|
||||
public function typeWasSpecified() : bool
|
||||
{
|
||||
return $this->typeSpecified;
|
||||
}
|
||||
}
|
||||
|
@ -609,8 +609,11 @@ class QueryBuilderTest extends OrmTestCase
|
||||
->setParameter('id', 1);
|
||||
|
||||
$parameter = new Parameter('id', 1, ParameterTypeInferer::inferType(1));
|
||||
$inferred = $qb->getParameter('id');
|
||||
|
||||
$this->assertEquals($parameter, $qb->getParameter('id'));
|
||||
self::assertSame($parameter->getValue(), $inferred->getValue());
|
||||
self::assertSame($parameter->getType(), $inferred->getType());
|
||||
self::assertFalse($inferred->typeWasSpecified());
|
||||
}
|
||||
|
||||
public function testSetParameters()
|
||||
|
Loading…
x
Reference in New Issue
Block a user