1
0
mirror of synced 2025-01-18 06:21:40 +03:00

annotation driver and basic support

This commit is contained in:
Fabio B. Silva 2012-02-26 16:51:39 -03:00
parent 2b996128af
commit bfc7986b20
14 changed files with 261 additions and 16 deletions

View File

@ -89,6 +89,22 @@ class EntityRepository implements ObjectRepository
return $this->_em->createQuery($this->_class->getNamedQuery($queryName));
}
/**
* Creates a native SQL query.
*
* @param string $queryName
* @return NativeQuery
*/
public function createNativeNamedQuery($queryName)
{
$queryMapping = $this->_class->getNamedNativeQuery($queryName);
$resultMapping = $this->_class->getSqlResultSetMapping($queryMapping['resultSetMapping']);
$rsm = new Query\ResultSetMappingBuilder($this->_em);
$rsm->addSqlResultSetMapping($resultMapping);
return $this->_em->createNativeQuery($queryMapping['query'], $rsm);
}
/**
* Clears the repository, causing all managed entities to become detached.
*/

View File

@ -1983,8 +1983,15 @@ class ClassMetadataInfo implements ClassMetadata
throw MappingException::missingQueryMapping($this->name, $queryMapping['name']);
}
if (isset($queryMapping['resultClass']) && $queryMapping['resultClass'] === '__CLASS__') {
$queryMapping['resultClass'] = $this->name;
if (isset($queryMapping['resultClass'])) {
if($queryMapping['resultClass'] === '__CLASS__') {
$queryMapping['resultClass'] = $this->name;
} else if (strlen($this->namespace) > 0 && strpos($queryMapping['resultClass'], '\\') === false) {
$queryMapping['resultClass'] = $this->namespace . '\\' . $queryMapping['resultClass'];
}
$mapping['targetEntity'] = ltrim($queryMapping['resultClass'], '\\');
}
$this->namedNativeQueries[$queryMapping['name']] = $queryMapping;
@ -2013,9 +2020,13 @@ class ClassMetadataInfo implements ClassMetadata
throw MappingException::missingResultSetMappingEntity($this->name, $resultMapping['name']);
}
if ($entityResult['entityClass'] === '__CLASS__') {
$resultMapping['entities'][$key]['entityClass'] = $this->name;
if($entityResult['entityClass'] === '__CLASS__') {
$entityResult['entityClass'] = $this->name;
} else if (strlen($this->namespace) > 0 && strpos($entityResult['entityClass'], '\\') === false) {
$entityResult['entityClass'] = $this->namespace . '\\' . $entityResult['entityClass'];
}
$resultMapping['entities'][$key]['entityClass'] = ltrim($entityResult['entityClass'], '\\');
}
}

View File

@ -204,15 +204,67 @@ class AnnotationDriver implements Driver
$metadata->setPrimaryTable($primaryTable);
}
// Evaluate NamedNativeQueries annotation
if (isset($classAnnotations['Doctrine\ORM\Mapping\NamedNativeQueries'])) {
$namedNativeQueriesAnnot = $classAnnotations['Doctrine\ORM\Mapping\NamedNativeQueries'];
foreach ($namedNativeQueriesAnnot->value as $namedNativeQuery) {
$metadata->addNamedNativeQuery(array(
'name' => $namedNativeQuery->name,
'query' => $namedNativeQuery->query,
'resultClass' => $namedNativeQuery->resultClass,
'resultSetMapping' => $namedNativeQuery->resultSetMapping,
));
}
}
// Evaluate SqlResultSetMappings annotation
if (isset($classAnnotations['Doctrine\ORM\Mapping\SqlResultSetMappings'])) {
$sqlResultSetMappingsAnnot = $classAnnotations['Doctrine\ORM\Mapping\SqlResultSetMappings'];
foreach ($sqlResultSetMappingsAnnot->value as $resultSetMapping) {
$entities = array();
foreach ($resultSetMapping->entities as $entityResultAnnot) {
$entityResult = array(
'fields' => array(),
'entityClass' => $entityResultAnnot->entityClass,
'discriminatorColumn' => $entityResultAnnot->discriminatorColumn,
);
foreach ($entityResultAnnot->fields as $fieldResultAnnot) {
$entityResult['fields'][] = array(
'name' => $fieldResultAnnot->name,
'column' => $fieldResultAnnot->column
);
}
$entities[] = $entityResult;
}
$columns = array();
foreach ($resultSetMapping->columns as $columnResultAnnot) {
$columns[] = array(
'name' => $resultSetMapping->name,
);
}
$metadata->addSqlResultSetMapping(array(
'name' => $resultSetMapping->name,
'entities' => $entities,
'columns' => $columns
));
}
}
// Evaluate NamedQueries annotation
if (isset($classAnnotations['Doctrine\ORM\Mapping\NamedQueries'])) {
$namedQueriesAnnot = $classAnnotations['Doctrine\ORM\Mapping\NamedQueries'];
$namedNativeQueriesAnnot = $classAnnotations['Doctrine\ORM\Mapping\NamedQueries'];
if (!is_array($namedQueriesAnnot->value)) {
if (!is_array($namedNativeQueriesAnnot->value)) {
throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations.");
}
foreach ($namedQueriesAnnot->value as $namedQuery) {
foreach ($namedNativeQueriesAnnot->value as $namedQuery) {
if (!($namedQuery instanceof \Doctrine\ORM\Mapping\NamedQuery)) {
throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations.");
}

View File

@ -53,3 +53,10 @@ require_once __DIR__.'/../PreRemove.php';
require_once __DIR__.'/../PostRemove.php';
require_once __DIR__.'/../PostLoad.php';
require_once __DIR__.'/../PreFlush.php';
require_once __DIR__.'/../FieldResult.php';
require_once __DIR__.'/../ColumnResult.php';
require_once __DIR__.'/../EntityResult.php';
require_once __DIR__.'/../NamedNativeQuery.php';
require_once __DIR__.'/../NamedNativeQueries.php';
require_once __DIR__.'/../SqlResultSetMapping.php';
require_once __DIR__.'/../SqlResultSetMappings.php';

View File

@ -46,7 +46,7 @@ final class EntityResult implements Annotation
*
* @var array<\Doctrine\ORM\Mapping\FieldResult>
*/
public $fields;
public $fields = array();
/**
* Specifies the column name of the column in the SELECT list that is used to determine the type of the entity instance.

View File

@ -36,5 +36,5 @@ final class NamedNativeQueries implements Annotation
*
* @var array<\Doctrine\ORM\Mapping\NamedNativeQuery>
*/
public $value;
public $value = array();
}

View File

@ -27,7 +27,7 @@ namespace Doctrine\ORM\Mapping;
* @since 2.3
*
* @Annotation
* @Target("CLASS")
* @Target("ANNOTATION")
*/
final class NamedNativeQuery implements Annotation
{

View File

@ -27,7 +27,7 @@ namespace Doctrine\ORM\Mapping;
* @since 2.3
*
* @Annotation
* @Target("CLASS")
* @Target("ANNOTATION")
*/
final class SqlResultSetMapping implements Annotation
{
@ -44,13 +44,13 @@ final class SqlResultSetMapping implements Annotation
*
* @var array<\Doctrine\ORM\Mapping\EntityResult>
*/
public $entities;
public $entities = array();
/**
* Specifies the result set mapping to scalar values.
*
* @var array<\Doctrine\ORM\Mapping\ColumnResult>
*/
public $columns;
public $columns = array();
}

View File

@ -36,5 +36,5 @@ final class SqlResultSetMappings implements Annotation
*
* @var array<\Doctrine\ORM\Mapping\SqlResultSetMapping>
*/
public $value;
public $value = array();
}

View File

@ -106,4 +106,37 @@ class ResultSetMappingBuilder extends ResultSetMapping
}
}
}
/**
* @param array $mapping
*/
public function addSqlResultSetMapping(array $mapping)
{
if (isset($mapping['entities'])) {
foreach ($mapping['entities'] as $key => $map) {
$simpleName = $map['entityClass'];
if (strpos($simpleName, '\\') !== false) {
$simpleName = substr($simpleName, strrpos($simpleName, '\\') + 1);
}
$className = $map['entityClass'];
$alias = strtolower($simpleName[0]) . $key;
$this->addEntityResult($className, $alias);
if (isset($map['fields'])) {
foreach ($map['fields'] as $field) {
$this->addFieldResult($alias, $field['column'], $field['name'], $className);
}
}
}
}
if (isset($mapping['columns'])) {
foreach ($mapping['columns'] as $map) {
$this->addScalarResult($map['name'], $map['name']);
}
}
}
}

View File

@ -8,6 +8,31 @@ namespace Doctrine\Tests\Models\CMS;
* @author Roman S. Borschel
* @Entity
* @Table(name="cms_addresses")
*
* @NamedNativeQueries({
* @NamedNativeQuery(
* name = "find-all",
* resultSetMapping = "mapping-find-all",
* query = "SELECT id, country, city FROM cms_addresses"
* )
* })
*
* @SqlResultSetMappings({
* @SqlResultSetMapping(
* name = "mapping-find-all",
* entities= {
* @EntityResult(
* entityClass = "CmsAddress",
* fields = {
* @FieldResult(name = "id", column="id"),
* @FieldResult(name = "city", column="city"),
* @FieldResult(name = "country", column="country")
* }
* )
* }
* )
* })
*
*/
class CmsAddress
{

View File

@ -329,5 +329,41 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
);
$users = $query->getResult();
}
/**
* @group DDC-1663
*/
public function testBasicNativeNamedQuery()
{
$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';
$user->setAddress($addr);
$this->_em->clear();
$this->_em->persist($user);
$this->_em->flush();
$this->_em->clear();
$repository = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsAddress');
$query = $repository->createNativeNamedQuery('find-all');
$result = $query->getResult();
$this->assertCount(1, $result);
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsAddress', $result[0]);
$this->assertEquals($addr->id, $result[0]->id);
$this->assertEquals($addr->city, $result[0]->city);
$this->assertEquals($addr->country, $result[0]->country);
}
}

View File

@ -93,5 +93,70 @@ class ResultSetMappingTest extends \Doctrine\Tests\OrmTestCase
$this->assertTrue($rms->hasParentAlias('p'));
$this->assertTrue($rms->isMixedResult());
}
/**
* @group DDC-1663
*/
public function testAddSqlResultSetMapping()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
$cm->addSqlResultSetMapping(array(
'name' => 'find-all',
'entities' => array(
array(
'entityClass' => '__CLASS__',
'fields' => array(
array(
'name' => 'id',
'column'=> 'user_id'
),
array(
'name' => 'name',
'column'=> 'user_name'
)
)
),
array(
'entityClass' => 'CmsEmail',
'fields' => array(
array(
'name' => 'id',
'column'=> 'email_id'
),
array(
'name' => 'email',
'column'=> 'email_email'
)
)
)
),
'columns' => array(
array(
'name' => 'scalarColumn'
)
)
));
$rsm = new \Doctrine\ORM\Query\ResultSetMappingBuilder($this->_em);
$rsm->addSqlResultSetMapping($cm->getSqlResultSetMapping('find-all'));
$this->assertEquals('scalarColumn', $rsm->getScalarAlias('scalarColumn'));
$this->assertEquals('c0', $rsm->getEntityAlias('user_id'));
$this->assertEquals('c0', $rsm->getEntityAlias('user_name'));
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $rsm->getClassName('c0'));
$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('Doctrine\Tests\Models\CMS\CmsEmail', $rsm->getClassName('c1'));
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsEmail', $rsm->getDeclaringClass('email_id'));
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsEmail', $rsm->getDeclaringClass('email_email'));
}
}