diff --git a/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php b/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php index ceacc9638..d1690b72c 100644 --- a/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php +++ b/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php @@ -20,6 +20,7 @@ namespace Doctrine\ORM\Query; use Doctrine\ORM\EntityManager; +use Doctrine\ORM\Mapping\ClassMetadataInfo; /** * A ResultSetMappingBuilder uses the EntityManager to automatically populate entity fields @@ -52,21 +53,7 @@ class ResultSetMappingBuilder extends ResultSetMapping public function addRootEntityFromClassMetadata($class, $alias, $renamedColumns = array()) { $this->addEntityResult($class, $alias); - $classMetadata = $this->em->getClassMetadata($class); - if ($classMetadata->isInheritanceTypeSingleTable() || $classMetadata->isInheritanceTypeJoined()) { - throw new \InvalidArgumentException('ResultSetMapping builder does not currently support inheritance.'); - } - $platform = $this->em->getConnection()->getDatabasePlatform(); - foreach ($classMetadata->getColumnNames() AS $columnName) { - $propertyName = $classMetadata->getFieldName($columnName); - if (isset($renamedColumns[$columnName])) { - $columnName = $renamedColumns[$columnName]; - } - if (isset($this->fieldMappings[$columnName])) { - throw new \InvalidArgumentException("The column '$columnName' conflicts with another column in the mapper."); - } - $this->addFieldResult($alias, $platform->getSQLResultCasing($columnName), $propertyName); - } + $this->addAllClassFields($class, $alias, $renamedColumns); } /** @@ -81,6 +68,14 @@ class ResultSetMappingBuilder extends ResultSetMapping public function addJoinedEntityFromClassMetadata($class, $alias, $parentAlias, $relation, $renamedColumns = array()) { $this->addJoinedEntityResult($class, $alias, $parentAlias, $relation); + $this->addAllClassFields($class, $alias, $renamedColumns); + } + + /** + * Adds all fields of the given class to the result set mapping (columns and meta fields) + */ + protected function addAllClassFields($class, $alias, $renamedColumns = array()) + { $classMetadata = $this->em->getClassMetadata($class); if ($classMetadata->isInheritanceTypeSingleTable() || $classMetadata->isInheritanceTypeJoined()) { throw new \InvalidArgumentException('ResultSetMapping builder does not currently support inheritance.'); @@ -96,5 +91,17 @@ class ResultSetMappingBuilder extends ResultSetMapping } $this->addFieldResult($alias, $platform->getSQLResultCasing($columnName), $propertyName); } + foreach ($classMetadata->associationMappings AS $associationMapping) { + if ($associationMapping['isOwningSide'] && $associationMapping['type'] & ClassMetadataInfo::TO_ONE) { + foreach ($associationMapping['joinColumns'] AS $joinColumn) { + $columnName = $joinColumn['name']; + $renamedColumnName = isset($renamedColumns[$columnName]) ? $renamedColumns[$columnName] : $columnName; + if (isset($this->metaMappings[$renamedColumnName])) { + throw new \InvalidArgumentException("The column '$renamedColumnName' conflicts with another column in the mapper."); + } + $this->addMetaResult($alias, $platform->getSQLResultCasing($renamedColumnName), $platform->getSQLResultCasing($columnName)); + } + } + } } } \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Functional/NativeQueryTest.php b/tests/Doctrine/Tests/ORM/Functional/NativeQueryTest.php index d9bda728c..3c41e0201 100644 --- a/tests/Doctrine/Tests/ORM/Functional/NativeQueryTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/NativeQueryTest.php @@ -52,6 +52,48 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $users[0]); $this->assertEquals('Roman', $users[0]->name); } + + public function testBasicNativeQueryWithMetaResult() + { + $user = new CmsUser; + $user->name = 'Roman'; + $user->username = 'romanb'; + $user->status = 'dev'; + + $addr = new CmsAddress; + $addr->country = 'germany'; + $addr->zip = 10827; + $addr->city = 'Berlin'; + + + $user->setAddress($addr); + + $this->_em->persist($user); + $this->_em->flush(); + + $this->_em->clear(); + + $rsm = new ResultSetMapping; + $rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsAddress', 'a'); + $rsm->addFieldResult('a', $this->platform->getSQLResultCasing('id'), 'id'); + $rsm->addFieldResult('a', $this->platform->getSQLResultCasing('country'), 'country'); + $rsm->addFieldResult('a', $this->platform->getSQLResultCasing('zip'), 'zip'); + $rsm->addFieldResult('a', $this->platform->getSQLResultCasing('city'), 'city'); + $rsm->addMetaResult('a', $this->platform->getSQLResultCasing('user_id'), 'user_id'); + + $query = $this->_em->createNativeQuery('SELECT a.id, a.country, a.zip, a.city, a.user_id FROM cms_addresses a WHERE a.id = ?', $rsm); + $query->setParameter(1, $addr->id); + + $addresses = $query->getResult(); + + $this->assertEquals(1, count($addresses)); + $this->assertTrue($addresses[0] instanceof CmsAddress); + $this->assertEquals($addr->country, $addresses[0]->country); + $this->assertEquals($addr->zip, $addresses[0]->zip); + $this->assertEquals($addr->city, $addresses[0]->city); + $this->assertEquals($addr->street, $addresses[0]->street); + $this->assertTrue($addresses[0]->user instanceof CmsUser); + } public function testJoinedOneToManyNativeQuery() { @@ -193,6 +235,17 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase $phones = $users[0]->getPhonenumbers(); $this->assertEquals(424242, $phones[0]->phonenumber); $this->assertTrue($phones[0]->getUser() === $users[0]); + + $this->_em->clear(); + + $rsm = new ResultSetMappingBuilder($this->_em); + $rsm->addRootEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsPhonenumber', 'p'); + $query = $this->_em->createNativeQuery('SELECT p.* FROM cms_phonenumbers p WHERE p.phonenumber = ?', $rsm); + $query->setParameter(1, $phone->phonenumber); + $phone = $query->getSingleResult(); + + $this->assertNotNull($phone->getUser()); + $this->assertEquals($user->name, $phone->getUser()->getName()); } public function testJoinedOneToOneNativeQueryWithRSMBuilder() @@ -235,6 +288,17 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertEquals('germany', $users[0]->getAddress()->getCountry()); $this->assertEquals(10827, $users[0]->getAddress()->getZipCode()); $this->assertEquals('Berlin', $users[0]->getAddress()->getCity()); + + $this->_em->clear(); + + $rsm = new ResultSetMappingBuilder($this->_em); + $rsm->addRootEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress', 'a'); + $query = $this->_em->createNativeQuery('SELECT a.* FROM cms_addresses a WHERE a.id = ?', $rsm); + $query->setParameter(1, $addr->getId()); + $address = $query->getSingleResult(); + + $this->assertNotNull($address->getUser()); + $this->assertEquals($user->name, $address->getUser()->getName()); } /**