diff --git a/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php b/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php index 517fd0036..ceacc9638 100644 --- a/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php +++ b/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php @@ -47,15 +47,25 @@ class ResultSetMappingBuilder extends ResultSetMapping * * @param string $class The class name of the root entity. * @param string $alias The unique alias to use for the root entity. - * @param string $prefix Prefix for columns + * @param array $renamedColumns Columns that have been renamed (tableColumnName => queryColumnName) */ - public function addRootEntityFromClassMetadata($class, $alias, $prefix = '') + 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) { - $this->addFieldResult($alias, $platform->getSQLResultCasing($prefix . $columnName), $classMetadata->getFieldName($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); } } @@ -66,15 +76,25 @@ class ResultSetMappingBuilder extends ResultSetMapping * @param string $alias The unique alias to use for the joined entity. * @param string $parentAlias The alias of the entity result that is the parent of this joined result. * @param object $relation The association field that connects the parent entity result with the joined entity result. - * @param string $prefix Prefix for columns + * @param array $renamedColumns Columns that have been renamed (tableColumnName => queryColumnName) */ - public function addJoinedEntityFromClassMetadata($class, $alias, $parentAlias, $relation, $prefix = '') + public function addJoinedEntityFromClassMetadata($class, $alias, $parentAlias, $relation, $renamedColumns = array()) { $this->addJoinedEntityResult($class, $alias, $parentAlias, $relation); $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) { - $this->addFieldResult($alias, $platform->getSQLResultCasing($prefix . $columnName), $classMetadata->getFieldName($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); } } } \ 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 1b1a713b8..2a09b8310 100644 --- a/tests/Doctrine/Tests/ORM/Functional/NativeQueryTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/NativeQueryTest.php @@ -7,6 +7,8 @@ use Doctrine\ORM\Query\ResultSetMappingBuilder; use Doctrine\Tests\Models\CMS\CmsUser; use Doctrine\Tests\Models\CMS\CmsPhonenumber; use Doctrine\Tests\Models\CMS\CmsAddress; +use Doctrine\Tests\Models\Company\CompanyFixContract; +use Doctrine\Tests\Models\Company\CompanyEmployee; require_once __DIR__ . '/../../TestInit.php'; @@ -177,8 +179,8 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase $rsm = new ResultSetMappingBuilder($this->_em); $rsm->addRootEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsUser', 'u'); - $rsm->addJoinedEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsPhonenumber', 'p', 'u', 'phonenumbers', 'p_'); - $query = $this->_em->createNativeQuery('SELECT u.*, p.phonenumber AS p_phonenumber FROM cms_users u INNER JOIN cms_phonenumbers p ON u.id = p.user_id WHERE username = ?', $rsm); + $rsm->addJoinedEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsPhonenumber', 'p', 'u', 'phonenumbers'); + $query = $this->_em->createNativeQuery('SELECT u.*, p.* FROM cms_users u LEFT JOIN cms_phonenumbers p ON u.id = p.user_id WHERE username = ?', $rsm); $query->setParameter(1, 'romanb'); $users = $query->getResult(); @@ -216,9 +218,9 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase $rsm = new ResultSetMappingBuilder($this->_em); $rsm->addRootEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsUser', 'u'); - $rsm->addJoinedEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress', 'a', 'u', 'address', 'a_'); + $rsm->addJoinedEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress', 'a', 'u', 'address', array('id' => 'a_id')); - $query = $this->_em->createNativeQuery('SELECT u.id, u.name, u.status, a.id AS a_id, a.country AS a_country, a.zip AS a_zip, a.city AS a_city FROM cms_users u INNER JOIN cms_addresses a ON u.id = a.user_id WHERE u.username = ?', $rsm); + $query = $this->_em->createNativeQuery('SELECT u.*, a.*, a.id AS a_id FROM cms_users u INNER JOIN cms_addresses a ON u.id = a.user_id WHERE u.username = ?', $rsm); $query->setParameter(1, 'romanb'); $users = $query->getResult(); @@ -234,5 +236,15 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertEquals(10827, $users[0]->getAddress()->getZipCode()); $this->assertEquals('Berlin', $users[0]->getAddress()->getCity()); } + + /** + * @expectedException \InvalidArgumentException + */ + public function testRSMBuilderThrowsExceptionOnColumnConflict() + { + $rsm = new ResultSetMappingBuilder($this->_em); + $rsm->addRootEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsUser', 'u'); + $rsm->addJoinedEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress', 'a', 'u', 'address'); + } }