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