Merge pull request #689 from FabioBatSilva/DDC-1995
[WIP][DDC-1995 ] Support metadata class as parameter for instance of expression
This commit is contained in:
commit
462173ad71
@ -3026,4 +3026,18 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
|
||||
return $className;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMetadataValue($name) {
|
||||
|
||||
if (isset($this->$name)) {
|
||||
return $this->$name;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,8 @@ use Doctrine\DBAL\LockMode;
|
||||
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;
|
||||
|
||||
/**
|
||||
* A Query object represents a DQL query.
|
||||
@ -268,6 +270,10 @@ final class Query extends AbstractQuery
|
||||
$executor->setQueryCacheProfile($this->_queryCacheProfile);
|
||||
}
|
||||
|
||||
if ($this->_resultSetMapping === null) {
|
||||
$this->_resultSetMapping = $this->_parserResult->getResultSetMapping();
|
||||
}
|
||||
|
||||
// Prepare parameters
|
||||
$paramMappings = $this->_parserResult->getParameterMappings();
|
||||
|
||||
@ -277,10 +283,6 @@ final class Query extends AbstractQuery
|
||||
|
||||
list($sqlParams, $types) = $this->processParameterMappings($paramMappings);
|
||||
|
||||
if ($this->_resultSetMapping === null) {
|
||||
$this->_resultSetMapping = $this->_parserResult->getResultSetMapping();
|
||||
}
|
||||
|
||||
return $executor->execute($this->_em->getConnection(), $sqlParams, $types);
|
||||
}
|
||||
|
||||
@ -299,16 +301,21 @@ final class Query extends AbstractQuery
|
||||
$types = array();
|
||||
|
||||
foreach ($this->parameters as $parameter) {
|
||||
$key = $parameter->getName();
|
||||
$key = $parameter->getName();
|
||||
$value = $parameter->getValue();
|
||||
|
||||
if ( ! isset($paramMappings[$key])) {
|
||||
throw QueryException::unknownParameter($key);
|
||||
}
|
||||
|
||||
$value = $this->processParameterValue($parameter->getValue());
|
||||
if (isset($this->_resultSetMapping->metadataParameterMapping[$key]) && $value instanceof ClassMetadata) {
|
||||
$value = $value->getMetadataValue($this->_resultSetMapping->metadataParameterMapping[$key]);
|
||||
}
|
||||
|
||||
$value = $this->processParameterValue($value);
|
||||
$type = ($parameter->getValue() === $value)
|
||||
? $parameter->getType()
|
||||
: Query\ParameterTypeInferer::inferType($value);
|
||||
: ParameterTypeInferer::inferType($value);
|
||||
|
||||
foreach ($paramMappings[$key] as $position) {
|
||||
$types[$position] = $type;
|
||||
|
@ -153,6 +153,13 @@ class ResultSetMapping
|
||||
*/
|
||||
public $newObjectMappings = array();
|
||||
|
||||
/**
|
||||
* Maps metadata parameter names to the metadata attribute.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $metadataParameterMapping = array();
|
||||
|
||||
/**
|
||||
* Adds an entity result to this ResultSetMapping.
|
||||
*
|
||||
@ -371,6 +378,17 @@ class ResultSetMapping
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a metadata parameter mappings.
|
||||
*
|
||||
* @param mixed $parameter The parameter name in the SQL result set.
|
||||
* @param string $attribute The metadata attribute.
|
||||
*/
|
||||
public function addMetadataParameterMapping($parameter, $attribute)
|
||||
{
|
||||
$this->metadataParameterMapping[$parameter] = $attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a column with a given name is mapped as a scalar result.
|
||||
*
|
||||
|
@ -1972,24 +1972,31 @@ class SqlWalker implements TreeWalker
|
||||
$sqlParameterList = array();
|
||||
|
||||
foreach ($instanceOfExpr->value as $parameter) {
|
||||
|
||||
if ($parameter instanceof AST\InputParameter) {
|
||||
|
||||
$this->rsm->addMetadataParameterMapping($parameter->name, 'discriminatorValue');
|
||||
|
||||
$sqlParameterList[] = $this->walkInputParameter($parameter);
|
||||
} else {
|
||||
// Get name from ClassMetadata to resolve aliases.
|
||||
$entityClassName = $this->em->getClassMetadata($parameter)->name;
|
||||
|
||||
if ($entityClassName == $class->name) {
|
||||
$sqlParameterList[] = $this->conn->quote($class->discriminatorValue);
|
||||
} else {
|
||||
$discrMap = array_flip($class->discriminatorMap);
|
||||
|
||||
if (!isset($discrMap[$entityClassName])) {
|
||||
throw QueryException::instanceOfUnrelatedClass($entityClassName, $class->rootEntityName);
|
||||
}
|
||||
|
||||
$sqlParameterList[] = $this->conn->quote($discrMap[$entityClassName]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get name from ClassMetadata to resolve aliases.
|
||||
$entityClassName = $this->em->getClassMetadata($parameter)->name;
|
||||
$discriminatorValue = $class->discriminatorValue;
|
||||
|
||||
if ($entityClassName !== $class->name) {
|
||||
$discrMap = array_flip($class->discriminatorMap);
|
||||
|
||||
if ( ! isset($discrMap[$entityClassName])) {
|
||||
throw QueryException::instanceOfUnrelatedClass($entityClassName, $class->rootEntityName);
|
||||
}
|
||||
|
||||
$discriminatorValue = $discrMap[$entityClassName];
|
||||
}
|
||||
|
||||
$sqlParameterList[] = $this->conn->quote($discriminatorValue);
|
||||
}
|
||||
|
||||
$sql .= '(' . implode(', ', $sqlParameterList) . ')';
|
||||
|
81
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1995Test.php
Normal file
81
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1995Test.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\Tests\Models\Company\CompanyPerson;
|
||||
use Doctrine\Tests\Models\Company\CompanyEmployee;
|
||||
|
||||
/**
|
||||
* @group DDC-1995
|
||||
*/
|
||||
class DDC1995Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
$this->useModelSet('company');
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function testIssue()
|
||||
{
|
||||
$person = new CompanyPerson;
|
||||
$person->setName('p1');
|
||||
|
||||
$employee = new CompanyEmployee;
|
||||
$employee->setName('Foo');
|
||||
$employee->setDepartment('bar');
|
||||
$employee->setSalary(1000);
|
||||
|
||||
$this->_em->persist($person);
|
||||
$this->_em->persist($employee);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$dql = 'SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF ?1';
|
||||
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\Company\CompanyEmployee');
|
||||
|
||||
$result = $this->_em->createQuery($dql)
|
||||
->setParameter(1, $class)
|
||||
->getResult();
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyEmployee', $result[0]);
|
||||
}
|
||||
|
||||
public function testQueryCache()
|
||||
{
|
||||
$person = new CompanyPerson;
|
||||
$person->setName('p1');
|
||||
|
||||
$employee = new CompanyEmployee;
|
||||
$employee->setName('Foo');
|
||||
$employee->setDepartment('bar');
|
||||
$employee->setSalary(1000);
|
||||
|
||||
$this->_em->persist($person);
|
||||
$this->_em->persist($employee);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$dql = 'SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF :type';
|
||||
$class1 = $this->_em->getClassMetadata('Doctrine\Tests\Models\Company\CompanyEmployee');
|
||||
$class2 = $this->_em->getClassMetadata('Doctrine\Tests\Models\Company\CompanyPerson');
|
||||
|
||||
$result1 = $this->_em->createQuery($dql)
|
||||
->setParameter('type', $class1)
|
||||
->useQueryCache(true)
|
||||
->getResult();
|
||||
|
||||
$result2 = $this->_em->createQuery($dql)
|
||||
->setParameter('type', $class2)
|
||||
->useQueryCache(true)
|
||||
->getResult();
|
||||
|
||||
$this->assertCount(1, $result1);
|
||||
$this->assertCount(1, $result2);
|
||||
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyEmployee', $result1[0]);
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyPerson', $result2[0]);
|
||||
$this->assertNotInstanceOf('Doctrine\Tests\Models\Company\CompanyEmployee', $result2[0]);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user