From 015ea809b0d9580bba546ea2fa8d8d0edab0d372 Mon Sep 17 00:00:00 2001 From: "Fabio B. Silva" Date: Sun, 26 Feb 2012 19:27:42 -0300 Subject: [PATCH] added support for resultClass and empty fields --- lib/Doctrine/ORM/EntityRepository.php | 3 +- .../ORM/Mapping/Driver/AnnotationDriver.php | 6 +- .../ORM/Query/ResultSetMappingBuilder.php | 57 +++++++--- .../ORM/Hydration/ResultSetMappingTest.php | 100 ++++++++++++++++-- 4 files changed, 136 insertions(+), 30 deletions(-) diff --git a/lib/Doctrine/ORM/EntityRepository.php b/lib/Doctrine/ORM/EntityRepository.php index 6c61855ef..f2f6a396f 100644 --- a/lib/Doctrine/ORM/EntityRepository.php +++ b/lib/Doctrine/ORM/EntityRepository.php @@ -98,9 +98,8 @@ class EntityRepository implements ObjectRepository public function createNativeNamedQuery($queryName) { $queryMapping = $this->_class->getNamedNativeQuery($queryName); - $resultMapping = $this->_class->getSqlResultSetMapping($queryMapping['resultSetMapping']); $rsm = new Query\ResultSetMappingBuilder($this->_em); - $rsm->addSqlResultSetMapping($resultMapping); + $rsm->addNamedNativeQueryMapping($this->_class, $queryMapping); return $this->_em->createNativeQuery($queryMapping['query'], $rsm); } diff --git a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php index 59b1733e0..9040b2103 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php @@ -258,13 +258,13 @@ class AnnotationDriver implements Driver // Evaluate NamedQueries annotation if (isset($classAnnotations['Doctrine\ORM\Mapping\NamedQueries'])) { - $namedNativeQueriesAnnot = $classAnnotations['Doctrine\ORM\Mapping\NamedQueries']; + $namedQueriesAnnot = $classAnnotations['Doctrine\ORM\Mapping\NamedQueries']; - if (!is_array($namedNativeQueriesAnnot->value)) { + if (!is_array($namedQueriesAnnot->value)) { throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations."); } - foreach ($namedNativeQueriesAnnot->value as $namedQuery) { + foreach ($namedQueriesAnnot->value as $namedQuery) { if (!($namedQuery instanceof \Doctrine\ORM\Mapping\NamedQuery)) { throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations."); } diff --git a/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php b/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php index 138b51ede..37a3ea45a 100644 --- a/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php +++ b/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php @@ -109,34 +109,57 @@ class ResultSetMappingBuilder extends ResultSetMapping /** - * @param array $mapping + * Adds a the mappings of the results of native SQL queries to the result set. + * + * @param ClassMetadataInfo $class + * @param array $queryMapping + * @return ResultSetMappingBuilder */ - public function addSqlResultSetMapping(array $mapping) + public function addNamedNativeQueryMapping(ClassMetadataInfo $class, array $queryMapping) { - if (isset($mapping['entities'])) { - foreach ($mapping['entities'] as $key => $map) { - $simpleName = $map['entityClass']; - if (strpos($simpleName, '\\') !== false) { - $simpleName = substr($simpleName, strrpos($simpleName, '\\') + 1); - } + if (isset($queryMapping['resultClass'])) { + $classMetadata = $this->em->getClassMetadata($queryMapping['resultClass']); + $shortName = $classMetadata->reflClass->getShortName(); + $alias = strtolower($shortName[0]).'0'; - $className = $map['entityClass']; - $alias = strtolower($simpleName[0]) . $key; + $this->addEntityResult($class->name, $alias); + + foreach ($classMetadata->getColumnNames() as $key => $columnName) { + $propertyName = $classMetadata->getFieldName($columnName); + $this->addFieldResult($alias, $columnName, $propertyName); + } + + return $this; + } + + $resultMapping = $class->getSqlResultSetMapping($queryMapping['resultSetMapping']); + if (isset($resultMapping['entities'])) { + foreach ($resultMapping['entities'] as $key => $entityMapping) { + $classMetadata = $this->em->getClassMetadata($entityMapping['entityClass']); + $shortName = $classMetadata->reflClass->getShortName(); + $alias = strtolower($shortName[0]) . $key; - $this->addEntityResult($className, $alias); + $this->addEntityResult($classMetadata->name, $alias); - if (isset($map['fields'])) { - foreach ($map['fields'] as $field) { - $this->addFieldResult($alias, $field['column'], $field['name'], $className); + if (isset($entityMapping['fields']) && !empty($entityMapping['fields'])) { + foreach ($entityMapping['fields'] as $field) { + $this->addFieldResult($alias, $field['column'], $field['name'], $classMetadata->name); + } + } else { + foreach ($classMetadata->getColumnNames() as $columnName) { + $propertyName = $classMetadata->getFieldName($columnName); + $this->addFieldResult($alias, $columnName, $propertyName); } } } } - if (isset($mapping['columns'])) { - foreach ($mapping['columns'] as $map) { - $this->addScalarResult($map['name'], $map['name']); + if (isset($resultMapping['columns'])) { + foreach ($resultMapping['columns'] as $entityMapping) { + $this->addScalarResult($entityMapping['name'], $entityMapping['name']); } } + + return $this; } } \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Hydration/ResultSetMappingTest.php b/tests/Doctrine/Tests/ORM/Hydration/ResultSetMappingTest.php index ba7421c7a..9c057a0b1 100644 --- a/tests/Doctrine/Tests/ORM/Hydration/ResultSetMappingTest.php +++ b/tests/Doctrine/Tests/ORM/Hydration/ResultSetMappingTest.php @@ -97,11 +97,16 @@ class ResultSetMappingTest extends \Doctrine\Tests\OrmTestCase /** * @group DDC-1663 */ - public function testAddSqlResultSetMapping() + public function testAddNamedNativeQueryResultSetMapping() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->addNamedNativeQuery(array( + 'name' => 'find-all', + 'query' => 'SELECT u.id AS user_id, e.id AS email_id, u.name, e.email, u.id + e.id AS scalarColumn FROM cms_users u INNER JOIN cms_emails e ON e.id = u.email_id', + 'resultSetMapping' => 'find-all', + )); $cm->addSqlResultSetMapping(array( 'name' => 'find-all', 'entities' => array( @@ -114,7 +119,7 @@ class ResultSetMappingTest extends \Doctrine\Tests\OrmTestCase ), array( 'name' => 'name', - 'column'=> 'user_name' + 'column'=> 'name' ) ) ), @@ -127,7 +132,7 @@ class ResultSetMappingTest extends \Doctrine\Tests\OrmTestCase ), array( 'name' => 'email', - 'column'=> 'email_email' + 'column'=> 'email' ) ) ) @@ -140,23 +145,102 @@ class ResultSetMappingTest extends \Doctrine\Tests\OrmTestCase )); + $queryMapping = $cm->getNamedNativeQuery('find-all'); + $rsm = new \Doctrine\ORM\Query\ResultSetMappingBuilder($this->_em); - $rsm->addSqlResultSetMapping($cm->getSqlResultSetMapping('find-all')); + $rsm->addNamedNativeQueryMapping($cm, $queryMapping); $this->assertEquals('scalarColumn', $rsm->getScalarAlias('scalarColumn')); $this->assertEquals('c0', $rsm->getEntityAlias('user_id')); - $this->assertEquals('c0', $rsm->getEntityAlias('user_name')); + $this->assertEquals('c0', $rsm->getEntityAlias('name')); $this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $rsm->getClassName('c0')); + $this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $rsm->getDeclaringClass('name')); $this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $rsm->getDeclaringClass('user_id')); - $this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $rsm->getDeclaringClass('user_name')); $this->assertEquals('c1', $rsm->getEntityAlias('email_id')); - $this->assertEquals('c1', $rsm->getEntityAlias('email_email')); + $this->assertEquals('c1', $rsm->getEntityAlias('email')); $this->assertEquals('Doctrine\Tests\Models\CMS\CmsEmail', $rsm->getClassName('c1')); + $this->assertEquals('Doctrine\Tests\Models\CMS\CmsEmail', $rsm->getDeclaringClass('email')); $this->assertEquals('Doctrine\Tests\Models\CMS\CmsEmail', $rsm->getDeclaringClass('email_id')); - $this->assertEquals('Doctrine\Tests\Models\CMS\CmsEmail', $rsm->getDeclaringClass('email_email')); + } + + /** + * @group DDC-1663 + */ + public function testAddNamedNativeQueryResultSetMappingWithoutFields() + { + $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); + $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + + $cm->addNamedNativeQuery(array( + 'name' => 'find-all', + 'query' => 'SELECT u.id AS user_id, e.id AS email_id, u.name, e.email, u.id + e.id AS scalarColumn FROM cms_users u INNER JOIN cms_emails e ON e.id = u.email_id', + 'resultSetMapping' => 'find-all', + )); + $cm->addSqlResultSetMapping(array( + 'name' => 'find-all', + 'entities' => array( + array( + 'entityClass' => '__CLASS__', + ) + ), + 'columns' => array( + array( + 'name' => 'scalarColumn' + ) + ) + )); + + + $queryMapping = $cm->getNamedNativeQuery('find-all'); + + $rsm = new \Doctrine\ORM\Query\ResultSetMappingBuilder($this->_em); + $rsm->addNamedNativeQueryMapping($cm, $queryMapping); + + $this->assertEquals('scalarColumn', $rsm->getScalarAlias('scalarColumn')); + + $this->assertEquals('c0', $rsm->getEntityAlias('id')); + $this->assertEquals('c0', $rsm->getEntityAlias('name')); + $this->assertEquals('c0', $rsm->getEntityAlias('status')); + $this->assertEquals('c0', $rsm->getEntityAlias('username')); + $this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $rsm->getClassName('c0')); + $this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $rsm->getDeclaringClass('id')); + $this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $rsm->getDeclaringClass('name')); + $this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $rsm->getDeclaringClass('status')); + $this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $rsm->getDeclaringClass('username')); + } + + /** + * @group DDC-1663 + */ + public function testAddNamedNativeQueryResultClass() + { + $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); + $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + + $cm->addNamedNativeQuery(array( + 'name' => 'find-all', + 'resultClass' => '__CLASS__', + 'query' => 'SELECT * FROM cms_users', + )); + + $queryMapping = $cm->getNamedNativeQuery('find-all'); + + $rsm = new \Doctrine\ORM\Query\ResultSetMappingBuilder($this->_em); + $rsm->addNamedNativeQueryMapping($cm, $queryMapping); + + + $this->assertEquals('c0', $rsm->getEntityAlias('id')); + $this->assertEquals('c0', $rsm->getEntityAlias('name')); + $this->assertEquals('c0', $rsm->getEntityAlias('status')); + $this->assertEquals('c0', $rsm->getEntityAlias('username')); + $this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $rsm->getClassName('c0')); + $this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $rsm->getDeclaringClass('id')); + $this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $rsm->getDeclaringClass('name')); + $this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $rsm->getDeclaringClass('status')); + $this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $rsm->getDeclaringClass('username')); } }