Browse files

Merge pull request #689 from FabioBatSilva/DDC-1995

[WIP][DDC-1995 ] Support metadata class as parameter for instance of expression
  • Loading branch information...
2 parents 5c7b98b + 710d0d1 commit 462173ad71ae63cd9877e1e642f7968ed1f9971b @guilhermeblanco guilhermeblanco committed Jun 7, 2013
View
14 lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
@@ -3026,4 +3026,18 @@ public function fullyQualifiedClassName($className)
return $className;
}
+
+ /**
+ * @param string $name
+ *
+ * @return mixed
+ */
+ public function getMetadataValue($name) {
+
+ if (isset($this->$name)) {
+ return $this->$name;
+ }
+
+ return null;
+ }
}
View
21 lib/Doctrine/ORM/Query.php
@@ -26,6 +26,8 @@
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 @@ protected function _doExecute()
$executor->setQueryCacheProfile($this->_queryCacheProfile);
}
+ if ($this->_resultSetMapping === null) {
+ $this->_resultSetMapping = $this->_parserResult->getResultSetMapping();
+ }
+
// Prepare parameters
$paramMappings = $this->_parserResult->getParameterMappings();
@@ -277,10 +283,6 @@ protected function _doExecute()
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 @@ private function processParameterMappings($paramMappings)
$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;
View
18 lib/Doctrine/ORM/Query/ResultSetMapping.php
@@ -154,6 +154,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.
*
* @param string $class The class name of the entity.
@@ -372,6 +379,17 @@ public function addScalarResult($columnName, $alias, $type = 'string')
}
/**
+ * 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.
*
* @param string $columnName The name of the column in the SQL result set.
View
29 lib/Doctrine/ORM/Query/SqlWalker.php
@@ -1972,24 +1972,31 @@ public function walkInstanceOfExpression($instanceOfExpr)
$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);
+ continue;
+ }
- if (!isset($discrMap[$entityClassName])) {
- throw QueryException::instanceOfUnrelatedClass($entityClassName, $class->rootEntityName);
- }
+ // 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);
- $sqlParameterList[] = $this->conn->quote($discrMap[$entityClassName]);
+ if ( ! isset($discrMap[$entityClassName])) {
+ throw QueryException::instanceOfUnrelatedClass($entityClassName, $class->rootEntityName);
}
+
+ $discriminatorValue = $discrMap[$entityClassName];
}
+
+ $sqlParameterList[] = $this->conn->quote($discriminatorValue);
}
$sql .= '(' . implode(', ', $sqlParameterList) . ')';
View
81 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1995Test.php
@@ -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]);
+ }
+}

0 comments on commit 462173a

Please sign in to comment.