1
0
mirror of synced 2025-01-17 22:11:41 +03:00

test multiple entity results

This commit is contained in:
Fabio B. Silva 2012-03-11 12:10:15 -03:00
parent 9c87b5c689
commit 52c49b444e
10 changed files with 352 additions and 46 deletions

View File

@ -2629,4 +2629,19 @@ class ClassMetadataInfo implements ClassMetadata
{
return $this->associationMappings[$fieldName]['mappedBy'];
}
/**
* @param string $targetClass
* @return array
*/
public function getAssociationsByTargetClass($targetClass)
{
$relations = array();
foreach ($this->associationMappings as $mapping) {
if ($mapping['targetEntity'] == $targetClass) {
$relations[$mapping['fieldName']] = $mapping;
}
}
return $relations;
}
}

View File

@ -172,54 +172,30 @@ class ResultSetMappingBuilder extends ResultSetMapping
*/
public function addNamedNativeQueryResultSetMapping(ClassMetadataInfo $class, $resultSetMappingName)
{
$resultMapping = $class->getSqlResultSetMapping($resultSetMappingName);
$counter = 0;
$resultMapping = $class->getSqlResultSetMapping($resultSetMappingName);
$rooShortName = $class->reflClass->getShortName();
$rootAlias = strtolower($rooShortName[0]) . $counter;
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;
if (isset($entityMapping['discriminatorColumn']) && $entityMapping['discriminatorColumn']) {
$discriminatorColumn = $entityMapping['discriminatorColumn'];
$this->setDiscriminatorColumn($alias, $discriminatorColumn);
$this->addMetaResult($alias, $discriminatorColumn, $discriminatorColumn);
}
$this->addEntityResult($classMetadata->name, $alias);
if (isset($entityMapping['fields']) && !empty($entityMapping['fields'])) {
foreach ($entityMapping['fields'] as $field) {
$fieldName = $field['name'];
$relation = null;
if(strpos($fieldName, '.')){
list($relation, $fieldName) = explode('.', $fieldName);
}
if (isset($classMetadata->associationMappings[$relation])) {
if($relation) {
$associationMapping = $classMetadata->associationMappings[$relation];
$joinAlias = $alias.$relation;
$parentAlias = $alias;
$this->addJoinedEntityResult($associationMapping['targetEntity'], $joinAlias, $parentAlias, $relation);
$this->addFieldResult($joinAlias, $field['column'], $fieldName);
}else {
$this->addFieldResult($alias, $field['column'], $fieldName, $classMetadata->name);
}
} else {
if(!isset($classMetadata->fieldMappings[$fieldName])) {
throw new \InvalidArgumentException("Entity '".$classMetadata->name."' has no field '".$fieldName."'. ");
}
$this->addFieldResult($alias, $field['column'], $fieldName, $classMetadata->name);
}
}
if ($class->reflClass->name == $classMetadata->reflClass->name) {
$this->addEntityResult($classMetadata->name, $rootAlias);
$this->addNamedNativeQueryEntityResultMapping($classMetadata, $entityMapping, $rootAlias);
} else {
foreach ($classMetadata->getColumnNames() as $columnName) {
$propertyName = $classMetadata->getFieldName($columnName);
$this->addFieldResult($alias, $columnName, $propertyName);
$shortName = $classMetadata->reflClass->getShortName();
$joinAlias = strtolower($shortName[0]) . ++ $counter;
$associations = $class->getAssociationsByTargetClass($classMetadata->name);
foreach ($associations as $relation => $mapping) {
$this->addJoinedEntityResult($mapping['targetEntity'], $joinAlias, $rootAlias, $relation);
$this->addNamedNativeQueryEntityResultMapping($classMetadata, $entityMapping, $joinAlias);
}
}
}
}
@ -231,4 +207,58 @@ class ResultSetMappingBuilder extends ResultSetMapping
return $this;
}
/**
* Adds the entity result mapping of the results of native SQL queries to the result set.
*
* @param ClassMetadataInfo $classMetadata
* @param array $entityMapping
* @param string $alias
* @return ResultSetMappingBuilder
*/
public function addNamedNativeQueryEntityResultMapping(ClassMetadataInfo $classMetadata, array $entityMapping, $alias)
{
if (isset($entityMapping['discriminatorColumn']) && $entityMapping['discriminatorColumn']) {
$discriminatorColumn = $entityMapping['discriminatorColumn'];
$this->setDiscriminatorColumn($alias, $discriminatorColumn);
$this->addMetaResult($alias, $discriminatorColumn, $discriminatorColumn);
}
if (isset($entityMapping['fields']) && !empty($entityMapping['fields'])) {
foreach ($entityMapping['fields'] as $field) {
$fieldName = $field['name'];
$relation = null;
if(strpos($fieldName, '.')){
list($relation, $fieldName) = explode('.', $fieldName);
}
if (isset($classMetadata->associationMappings[$relation])) {
if($relation) {
$associationMapping = $classMetadata->associationMappings[$relation];
$joinAlias = $alias.$relation;
$parentAlias = $alias;
$this->addJoinedEntityResult($associationMapping['targetEntity'], $joinAlias, $parentAlias, $relation);
$this->addFieldResult($joinAlias, $field['column'], $fieldName);
}else {
$this->addFieldResult($alias, $field['column'], $fieldName, $classMetadata->name);
}
} else {
if(!isset($classMetadata->fieldMappings[$fieldName])) {
throw new \InvalidArgumentException("Entity '".$classMetadata->name."' has no field '".$fieldName."'. ");
}
$this->addFieldResult($alias, $field['column'], $fieldName, $classMetadata->name);
}
}
} else {
foreach ($classMetadata->getColumnNames() as $columnName) {
$propertyName = $classMetadata->getFieldName($columnName);
$this->addFieldResult($alias, $columnName, $propertyName);
}
}
return $this;
}
}

View File

@ -37,6 +37,11 @@ use Doctrine\Common\Collections\ArrayCollection;
* resultSetMapping= "mappingUserPhonenumberCount",
* query = "SELECT id, name, status, COUNT(phonenumber) AS numphones FROM cms_users INNER JOIN cms_phonenumbers ON id = user_id WHERE username IN (?) GROUP BY id, name, status, username ORDER BY username"
* ),
* @NamedNativeQuery(
* name = "fetchMultipleJoinsEntityResults",
* resultSetMapping= "mappingMultipleJoinsEntityResults",
* query = "SELECT u.id AS u_id, u.name AS u_name, u.status AS u_status, a.id AS a_id, a.zip AS a_zip, a.country AS a_country, COUNT(p.phonenumber) AS numphones FROM cms_users u INNER JOIN cms_addresses a ON u.id = a.user_id INNER JOIN cms_phonenumbers p ON u.id = p.user_id GROUP BY u.id, u.name, u.status, u.username, a.id, a.zip, a.country ORDER BY u.username"
* ),
* })
*
* @SqlResultSetMappings({
@ -86,6 +91,30 @@ use Doctrine\Common\Collections\ArrayCollection;
* columns = {
* @ColumnResult("numphones")
* }
* ),
* @SqlResultSetMapping(
* name = "mappingMultipleJoinsEntityResults",
* entities= {
* @EntityResult(
* entityClass = "__CLASS__",
* fields = {
* @FieldResult(name = "id", column="u_id"),
* @FieldResult(name = "name", column="u_name"),
* @FieldResult(name = "status", column="u_status"),
* }
* ),
* @EntityResult(
* entityClass = "CmsAddress",
* fields = {
* @FieldResult(name = "id", column="a_id"),
* @FieldResult(name = "zip", column="a_zip"),
* @FieldResult(name = "country", column="a_country"),
* }
* )
* },
* columns = {
* @ColumnResult("numphones")
* }
* )
* })
*/
@ -255,6 +284,12 @@ class CmsUser
'resultSetMapping' => 'mappingUserPhonenumberCount',
));
$metadata->addNamedNativeQuery(array (
"name" => "fetchMultipleJoinsEntityResults",
"resultSetMapping" => "mappingMultipleJoinsEntityResults",
"query" => "SELECT u.id AS u_id, u.name AS u_name, u.status AS u_status, a.id AS a_id, a.zip AS a_zip, a.country AS a_country, COUNT(p.phonenumber) AS numphones FROM cms_users u INNER JOIN cms_addresses a ON u.id = a.user_id INNER JOIN cms_phonenumbers p ON u.id = p.user_id GROUP BY u.id, u.name, u.status, u.username, a.id, a.zip, a.country ORDER BY u.username"
));
$metadata->addSqlResultSetMapping(array (
'name' => 'mappingJoinedAddress',
'columns' => array(),
@ -352,5 +387,51 @@ class CmsUser
)
)
));
$metadata->addSqlResultSetMapping(array(
'name' => 'mappingMultipleJoinsEntityResults',
'entities' => array(array(
'fields' => array(
array(
'name' => 'id',
'column' => 'u_id',
),
array(
'name' => 'name',
'column' => 'u_name',
),
array(
'name' => 'status',
'column' => 'u_status',
)
),
'entityClass' => 'Doctrine\Tests\Models\CMS\CmsUser',
'discriminatorColumn' => null,
),
array(
'fields' => array(
array(
'name' => 'id',
'column' => 'a_id',
),
array(
'name' => 'zip',
'column' => 'a_zip',
),
array(
'name' => 'country',
'column' => 'a_country',
),
),
'entityClass' => 'Doctrine\Tests\Models\CMS\CmsAddress',
'discriminatorColumn' => null,
),
),
'columns' => array(array(
'name' => 'numphones',
)
)
));
}
}

View File

@ -8,6 +8,7 @@ use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
use Doctrine\Tests\Models\CMS\CmsAddress;
use Doctrine\Tests\Models\CMS\CmsEmail;
use Doctrine\Tests\Models\CMS\CmsArticle;
use Doctrine\Tests\Models\Company\CompanyFixContract;
use Doctrine\Tests\Models\Company\CompanyEmployee;
use Doctrine\Tests\Models\Company\CompanyPerson;
@ -596,4 +597,55 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals('Fabio Silva', $result[1]->getName());
}
/**
* @group DDC-1663
* DQL : SELECT u, a, COUNT(p) AS numphones FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.address a JOIN u.phonenumbers p
*/
public function testMultipleEntityResults()
{
$user = new CmsUser;
$user->name = 'Fabio B. Silva';
$user->username = 'FabioBatSilva';
$user->status = 'dev';
$addr = new CmsAddress;
$addr->country = 'Brazil';
$addr->zip = 10827;
$addr->city = 'São Paulo';
$phone = new CmsPhonenumber;
$phone->phonenumber = 424242;
$user->setAddress($addr);
$user->addPhonenumber($phone);
$this->_em->clear();
$this->_em->persist($user);
$this->_em->flush();
$this->_em->clear();
$repository = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser');
$query = $repository->createNativeNamedQuery('fetchMultipleJoinsEntityResults');
$result = $query->getResult();
$this->assertEquals(1, count($result));
$this->assertTrue(is_array($result[0]));
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $result[0][0]);
$this->assertEquals('Fabio B. Silva', $result[0][0]->name);
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsAddress', $result[0][0]->getAddress());
$this->assertTrue($result[0][0]->getAddress()->getUser() == $result[0][0]);
$this->assertEquals('Brazil', $result[0][0]->getAddress()->getCountry());
$this->assertEquals(10827, $result[0][0]->getAddress()->getZipCode());
$this->assertEquals(1, $result[0]['numphones']);
}
}

View File

@ -102,6 +102,19 @@ class ResultSetMappingTest extends \Doctrine\Tests\OrmTestCase
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
$cm->mapOneToOne(array(
'fieldName' => 'email',
'targetEntity' => 'Doctrine\Tests\Models\CMS\CmsEmail',
'cascade' => array('persist'),
'inversedBy' => 'user',
'orphanRemoval' => false,
'joinColumns' => array(array(
'nullable' => true,
'referencedColumnName' => 'id',
)
)
));
$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',
@ -144,7 +157,7 @@ class ResultSetMappingTest extends \Doctrine\Tests\OrmTestCase
)
));
$queryMapping = $cm->getNamedNativeQuery('find-all');
$rsm = new \Doctrine\ORM\Query\ResultSetMappingBuilder($this->_em);

View File

@ -553,7 +553,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
$personMetadata = $this->createClassMetadata('Doctrine\Tests\Models\Company\CompanyPerson');
// user asserts
$this->assertCount(3, $userMetadata->getSqlResultSetMappings());
$this->assertCount(4, $userMetadata->getSqlResultSetMappings());
$mapping = $userMetadata->getSqlResultSetMapping('mappingJoinedAddress');
$this->assertEquals(array(),$mapping['columns']);
@ -588,6 +588,20 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals(array('name'=>'status','column'=>'status'), $mapping['entities'][0]['fields'][2]);
$this->assertEquals($userMetadata->name, $mapping['entities'][0]['entityClass']);
$mapping = $userMetadata->getSqlResultSetMapping('mappingMultipleJoinsEntityResults');
$this->assertEquals(array('name'=>'numphones'),$mapping['columns'][0]);
$this->assertEquals('mappingMultipleJoinsEntityResults', $mapping['name']);
$this->assertNull($mapping['entities'][0]['discriminatorColumn']);
$this->assertEquals(array('name'=>'id','column'=>'u_id'), $mapping['entities'][0]['fields'][0]);
$this->assertEquals(array('name'=>'name','column'=>'u_name'), $mapping['entities'][0]['fields'][1]);
$this->assertEquals(array('name'=>'status','column'=>'u_status'), $mapping['entities'][0]['fields'][2]);
$this->assertEquals($userMetadata->name, $mapping['entities'][0]['entityClass']);
$this->assertNull($mapping['entities'][1]['discriminatorColumn']);
$this->assertEquals(array('name'=>'id','column'=>'a_id'), $mapping['entities'][1]['fields'][0]);
$this->assertEquals(array('name'=>'zip','column'=>'a_zip'), $mapping['entities'][1]['fields'][1]);
$this->assertEquals(array('name'=>'country','column'=>'a_country'), $mapping['entities'][1]['fields'][2]);
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsAddress', $mapping['entities'][1]['entityClass']);
//person asserts
$this->assertCount(1, $personMetadata->getSqlResultSetMappings());

View File

@ -36,6 +36,12 @@ $metadata->addNamedNativeQuery(array (
'resultSetMapping' => 'mappingUserPhonenumberCount',
));
$metadata->addNamedNativeQuery(array (
"name" => "fetchMultipleJoinsEntityResults",
"resultSetMapping" => "mappingMultipleJoinsEntityResults",
"query" => "SELECT u.id AS u_id, u.name AS u_name, u.status AS u_status, a.id AS a_id, a.zip AS a_zip, a.country AS a_country, COUNT(p.phonenumber) AS numphones FROM cms_users u INNER JOIN cms_addresses a ON u.id = a.user_id INNER JOIN cms_phonenumbers p ON u.id = p.user_id GROUP BY u.id, u.name, u.status, u.username, a.id, a.zip, a.country ORDER BY u.username"
));
$metadata->addSqlResultSetMapping(array (
'name' => 'mappingJoinedAddress',
'columns' => array(),
@ -132,4 +138,49 @@ $metadata->addSqlResultSetMapping(array (
'name' => 'numphones',
)
)
));
$metadata->addSqlResultSetMapping(array(
'name' => 'mappingMultipleJoinsEntityResults',
'entities' => array(array(
'fields' => array(
array(
'name' => 'id',
'column' => 'u_id',
),
array(
'name' => 'name',
'column' => 'u_name',
),
array(
'name' => 'status',
'column' => 'u_status',
)
),
'entityClass' => 'Doctrine\Tests\Models\CMS\CmsUser',
'discriminatorColumn' => null,
),
array(
'fields' => array(
array(
'name' => 'id',
'column' => 'a_id',
),
array(
'name' => 'zip',
'column' => 'a_zip',
),
array(
'name' => 'country',
'column' => 'a_country',
),
),
'entityClass' => 'Doctrine\Tests\Models\CMS\CmsAddress',
'discriminatorColumn' => null,
),
),
'columns' => array(array(
'name' => 'numphones',
)
)
));

View File

@ -31,6 +31,10 @@
<named-native-query name="fetchUserPhonenumberCount" result-set-mapping="mappingUserPhonenumberCount">
<query>SELECT id, name, status, COUNT(phonenumber) AS numphones FROM cms_users INNER JOIN cms_phonenumbers ON id = user_id WHERE username IN (?) GROUP BY id, name, status, username ORDER BY username</query>
</named-native-query>
<named-native-query name="fetchMultipleJoinsEntityResults" result-set-mapping="mappingMultipleJoinsEntityResults">
<query>SELECT u.id AS u_id, u.name AS u_name, u.status AS u_status, a.id AS a_id, a.zip AS a_zip, a.country AS a_country, COUNT(p.phonenumber) AS numphones FROM cms_users u INNER JOIN cms_addresses a ON u.id = a.user_id INNER JOIN cms_phonenumbers p ON u.id = p.user_id GROUP BY u.id, u.name, u.status, u.username, a.id, a.zip, a.country ORDER BY u.username</query>
</named-native-query>
</named-native-queries>
<sql-result-set-mappings>
@ -63,6 +67,20 @@
</entity-result>
<column-result name="numphones"/>
</sql-result-set-mapping>
<sql-result-set-mapping name="mappingMultipleJoinsEntityResults">
<entity-result entity-class="__CLASS__">
<field-result name="id" column="u_id"/>
<field-result name="name" column="u_name"/>
<field-result name="status" column="u_status"/>
</entity-result>
<entity-result entity-class="CmsAddress">
<field-result name="id" column="a_id"/>
<field-result name="zip" column="a_zip"/>
<field-result name="country" column="a_country"/>
</entity-result>
<column-result name="numphones"/>
</sql-result-set-mapping>
</sql-result-set-mappings>
<id name="id" type="integer" column="id">

View File

@ -11,9 +11,7 @@
<named-native-query name="fetchAllWithResultClass" result-class="__CLASS__">
<query>SELECT id, name, discr FROM company_persons ORDER BY name</query>
</named-native-query>
</named-native-queries>
<named-native-queries>
<named-native-query name="fetchAllWithSqlResultSetMapping" result-set-mapping="mappingFetchAll">
<query>SELECT id, name, discr AS discriminator FROM company_persons ORDER BY name</query>
</named-native-query>

View File

@ -23,6 +23,10 @@ Doctrine\Tests\Models\CMS\CmsUser:
name: fetchUserPhonenumberCount
resultSetMapping: mappingUserPhonenumberCount
query: SELECT id, name, status, COUNT(phonenumber) AS numphones FROM cms_users INNER JOIN cms_phonenumbers ON id = user_id WHERE username IN (?) GROUP BY id, name, status, username ORDER BY username
fetchMultipleJoinsEntityResults:
name: fetchMultipleJoinsEntityResults
resultSetMapping: mappingMultipleJoinsEntityResults
query: SELECT u.id AS u_id, u.name AS u_name, u.status AS u_status, a.id AS a_id, a.zip AS a_zip, a.country AS a_country, COUNT(p.phonenumber) AS numphones FROM cms_users u INNER JOIN cms_addresses a ON u.id = a.user_id INNER JOIN cms_phonenumbers p ON u.id = p.user_id GROUP BY u.id, u.name, u.status, u.username, a.id, a.zip, a.country ORDER BY u.username
sqlResultSetMappings:
mappingJoinedAddress:
@ -75,6 +79,36 @@ Doctrine\Tests\Models\CMS\CmsUser:
name: name
2:
name: status
mappingMultipleJoinsEntityResults:
name: mappingMultipleJoinsEntityResults
columnResult:
0:
name: numphones
entityResult:
0:
entityClass: __CLASS__
fieldResult:
0:
name: id
column: u_id
1:
name: name
column: u_name
2:
name: status
column: u_status
1:
entityClass: CmsAddress
fieldResult:
0:
name: id
column: a_id
1:
name: zip
column: a_zip
2:
name: country
column: a_country
id:
id:
type: integer