1
0
mirror of synced 2025-02-03 05:49:25 +03:00

Fix discriminator resolution when using parameters

This commit is contained in:
Sergio Santoro 2017-06-24 13:35:44 +02:00
parent b1f7c59ed5
commit e91dcf8fb4
4 changed files with 58 additions and 23 deletions

View File

@ -371,6 +371,25 @@ final class Query extends AbstractQuery
$this->_em->getCache()->evictEntityRegion($className); $this->_em->getCache()->evictEntityRegion($className);
} }
private function getAllDiscriminators(ClassMetadata $classMetadata)
{
// FIXME: this code is copied from SqlWalker->getAllDiscriminators()
$hierarchyClasses = $classMetadata->subClasses;
$hierarchyClasses[] = $classMetadata->name;
$discriminators = [];
foreach ($hierarchyClasses as $class) {
$currentMetadata = $this->getEntityManager()->getClassMetadata($class);
$currentDiscriminator = $currentMetadata->discriminatorValue;
if (null !== $currentDiscriminator) {
$discriminators[$currentDiscriminator] = null;
}
}
return $discriminators;
}
/** /**
* Processes query parameter mappings. * Processes query parameter mappings.
* *
@ -398,6 +417,10 @@ final class Query extends AbstractQuery
$value = $value->getMetadataValue($rsm->metadataParameterMapping[$key]); $value = $value->getMetadataValue($rsm->metadataParameterMapping[$key]);
} }
if (isset($rsm->discriminatorParameters[$key]) && $value instanceof ClassMetadata) {
$value = array_keys($this->getAllDiscriminators($value));
}
$value = $this->processParameterValue($value); $value = $this->processParameterValue($value);
$type = ($parameter->getValue() === $value) $type = ($parameter->getValue() === $value)
? $parameter->getType() ? $parameter->getType()

View File

@ -168,6 +168,13 @@ class ResultSetMapping
*/ */
public $metadataParameterMapping = []; public $metadataParameterMapping = [];
/**
* Contains query parameter names to be resolved as discriminator values
*
* @var array
*/
public $discriminatorParameters = [];
/** /**
* Adds an entity result to this ResultSetMapping. * Adds an entity result to this ResultSetMapping.
* *

View File

@ -2270,42 +2270,29 @@ class SqlWalker implements TreeWalker
} }
/** /**
* @param ClassMetadataInfo $discrClass * @param ClassMetadataInfo $rootClass
* @param AST\InstanceOfExpression $instanceOfExpr * @param AST\InstanceOfExpression $instanceOfExpr
* @return string The list in parentheses of valid child discriminators from the given class * @return string The list in parentheses of valid child discriminators from the given class
* @throws QueryException * @throws QueryException
*/ */
private function getChildDiscriminatorsFromClassMetadata(ClassMetadataInfo $discrClass, AST\InstanceOfExpression $instanceOfExpr) private function getChildDiscriminatorsFromClassMetadata(ClassMetadataInfo $rootClass, AST\InstanceOfExpression $instanceOfExpr)
{ {
$sqlParameterList = []; $sqlParameterList = [];
$discriminators = []; $discriminators = [];
foreach ($instanceOfExpr->value as $parameter) { foreach ($instanceOfExpr->value as $parameter) {
if ($parameter instanceof AST\InputParameter) { if ($parameter instanceof AST\InputParameter) {
$this->rsm->addMetadataParameterMapping($parameter->name, 'discriminatorValue'); $this->rsm->discriminatorParameters[$parameter->name] = $parameter->name;
$sqlParameterList[] = $this->walkInParameter($parameter);
$sqlParameterList[] = $this->walkInputParameter($parameter);
continue; continue;
} }
$metadata = $this->em->getClassMetadata($parameter); $metadata = $this->em->getClassMetadata($parameter);
if ($metadata->getName() !== $discrClass->name && ! $metadata->getReflectionClass()->isSubclassOf($discrClass->name)) { if ($metadata->getName() !== $rootClass->name && ! $metadata->getReflectionClass()->isSubclassOf($rootClass->name)) {
throw QueryException::instanceOfUnrelatedClass($parameter, $discrClass->name); throw QueryException::instanceOfUnrelatedClass($parameter, $rootClass->name);
} }
// Include discriminators for parameter class and its subclass $discriminators = $discriminators + $this->getAllDiscriminators($metadata);
$hierarchyClasses = $metadata->subClasses;
$hierarchyClasses[] = $metadata->name;
foreach ($hierarchyClasses as $class) {
$currentMetadata = $this->em->getClassMetadata($class);
$currentDiscriminator = $currentMetadata->discriminatorValue;
if (null !== $currentDiscriminator) {
$discriminators[$currentDiscriminator] = null;
}
}
} }
foreach (array_keys($discriminators) as $dis) { foreach (array_keys($discriminators) as $dis) {
@ -2314,4 +2301,23 @@ class SqlWalker implements TreeWalker
return '(' . implode(', ', $sqlParameterList) . ')'; return '(' . implode(', ', $sqlParameterList) . ')';
} }
private function getAllDiscriminators(ClassMetadata $classMetadata)
{
// FIXME: this code is identical to Query->getAllDiscriminators()
$hierarchyClasses = $classMetadata->subClasses;
$hierarchyClasses[] = $classMetadata->name;
$discriminators = [];
foreach ($hierarchyClasses as $class) {
$currentMetadata = $this->em->getClassMetadata($class);
$currentDiscriminator = $currentMetadata->discriminatorValue;
if (null !== $currentDiscriminator) {
$discriminators[$currentDiscriminator] = null;
}
}
return $discriminators;
}
} }

View File

@ -72,10 +72,9 @@ class DDC1995Test extends \Doctrine\Tests\OrmFunctionalTestCase
->getResult(); ->getResult();
$this->assertCount(1, $result1); $this->assertCount(1, $result1);
$this->assertCount(1, $result2); $this->assertCount(2, $result2);
$this->assertInstanceOf(CompanyEmployee::class, $result1[0]); $this->assertInstanceOf(CompanyEmployee::class, $result1[0]);
$this->assertInstanceOf(CompanyPerson::class, $result2[0]); $this->assertContainsOnlyInstancesOf(CompanyPerson::class, $result2);
$this->assertNotInstanceOf(CompanyEmployee::class, $result2[0]);
} }
} }