1
0
mirror of synced 2025-01-18 22:41:43 +03:00

Merge pull request #293 from FabioBatSilva/DDC-1663

[DDC-1663]Native SQL Query Result Set Mappings
This commit is contained in:
Guilherme Blanco 2012-04-16 12:06:26 -07:00
commit bad811df6a
36 changed files with 3470 additions and 19 deletions

View File

@ -84,6 +84,51 @@
</xs:sequence>
</xs:complexType>
<xs:complexType name="named-native-query">
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="query" type="xs:string" use="required"/>
<xs:attribute name="result-class" type="xs:string" />
<xs:attribute name="result-set-mapping" type="xs:string" />
</xs:complexType>
<xs:complexType name="named-native-queries">
<xs:sequence>
<xs:element name="named-native-query" type="orm:named-native-query" minOccurs="1" maxOccurs="unbounded" />
<xs:any minOccurs="1" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="column-result">
<xs:attribute name="name" type="xs:string" use="required" />
</xs:complexType>
<xs:complexType name="field-result">
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="column" type="xs:string" />
</xs:complexType>
<xs:complexType name="entity-result">
<xs:sequence>
<xs:element name="field-result" type="orm:field-result" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="entity-class" type="xs:string" use="required" />
</xs:complexType>
<xs:complexType name="sql-result-set-mapping">
<xs:sequence>
<xs:element name="entity-result" type="orm:entity-result" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="column-result" type="orm:column-result" minOccurs="0" maxOccurs="unbounded" />
<xs:any minOccurs="1" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="sql-result-set-mappings">
<xs:sequence>
<xs:element name="sql-result-set-mapping" type="orm:sql-result-set-mapping" minOccurs="1" maxOccurs="unbounded" />
<xs:any minOccurs="1" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="entity">
<xs:sequence>
<xs:element name="options" type="orm:options" minOccurs="0" />
@ -93,6 +138,7 @@
<xs:element name="discriminator-map" type="orm:discriminator-map" minOccurs="0"/>
<xs:element name="lifecycle-callbacks" type="orm:lifecycle-callbacks" minOccurs="0" maxOccurs="1" />
<xs:element name="named-queries" type="orm:named-queries" minOccurs="0" maxOccurs="1" />
<xs:element name="named-native-queries" type="orm:named-native-queries" minOccurs="0" maxOccurs="1" />
<xs:element name="id" type="orm:id" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="field" type="orm:field" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="one-to-one" type="orm:one-to-one" minOccurs="0" maxOccurs="unbounded"/>

View File

@ -89,6 +89,21 @@ 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);
$rsm = new Query\ResultSetMappingBuilder($this->_em);
$rsm->addNamedNativeQueryMapping($this->_class, $queryMapping);
return $this->_em->createNativeQuery($queryMapping['query'], $rsm);
}
/**
* Clears the repository, causing all managed entities to become detached.
*/

View File

@ -326,6 +326,14 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
$this->addInheritedNamedQueries($class, $parent);
}
if ($parent && !empty ($parent->namedNativeQueries)) {
$this->addInheritedNamedNativeQueries($class, $parent);
}
if ($parent && !empty ($parent->sqlResultSetMappings)) {
$this->addInheritedSqlResultSetMappings($class, $parent);
}
$class->setParentClasses($visited);
if ($this->evm->hasListeners(Events::loadClassMetadata)) {
@ -466,6 +474,58 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
}
}
/**
* Adds inherited named native queries to the subclass mapping.
*
* @since 2.3
* @param \Doctrine\ORM\Mapping\ClassMetadata $subClass
* @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass
*/
private function addInheritedNamedNativeQueries(ClassMetadata $subClass, ClassMetadata $parentClass)
{
foreach ($parentClass->namedNativeQueries as $name => $query) {
if (!isset ($subClass->namedNativeQueries[$name])) {
$subClass->addNamedNativeQuery(array(
'name' => $query['name'],
'query' => $query['query'],
'isSelfClass' => $query['isSelfClass'],
'resultSetMapping' => $query['resultSetMapping'],
'resultClass' => $query['isSelfClass'] ? $subClass->name : $query['resultClass'],
));
}
}
}
/**
* Adds inherited sql result set mappings to the subclass mapping.
*
* @since 2.3
* @param \Doctrine\ORM\Mapping\ClassMetadata $subClass
* @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass
*/
private function addInheritedSqlResultSetMappings(ClassMetadata $subClass, ClassMetadata $parentClass)
{
foreach ($parentClass->sqlResultSetMappings as $name => $mapping) {
if (!isset ($subClass->sqlResultSetMappings[$name])) {
$entities = array();
foreach ($mapping['entities'] as $entity) {
$entities[] = array(
'fields' => $entity['fields'],
'isSelfClass' => $entity['isSelfClass'],
'discriminatorColumn' => $entity['discriminatorColumn'],
'entityClass' => $entity['isSelfClass'] ? $subClass->name : $entity['entityClass'],
);
}
$subClass->addSqlResultSetMapping(array(
'name' => $mapping['name'],
'columns' => $mapping['columns'],
'entities' => $entities,
));
}
}
}
/**
* Completes the ID generator mapping. If "auto" is specified we choose the generator
* most appropriate for the targeted database platform.

View File

@ -49,16 +49,19 @@ class ClassMetadataInfo implements ClassMetadata
* and therefore does not need an inheritance mapping type.
*/
const INHERITANCE_TYPE_NONE = 1;
/**
* JOINED means the class will be persisted according to the rules of
* <tt>Class Table Inheritance</tt>.
*/
const INHERITANCE_TYPE_JOINED = 2;
/**
* SINGLE_TABLE means the class will be persisted according to the rules of
* <tt>Single Table Inheritance</tt>.
*/
const INHERITANCE_TYPE_SINGLE_TABLE = 3;
/**
* TABLE_PER_CLASS means the class will be persisted according to the rules
* of <tt>Concrete Table Inheritance</tt>.
@ -71,17 +74,20 @@ class ClassMetadataInfo implements ClassMetadata
* Offers full portability.
*/
const GENERATOR_TYPE_AUTO = 1;
/**
* SEQUENCE means a separate sequence object will be used. Platforms that do
* not have native sequence support may emulate it. Full portability is currently
* not guaranteed.
*/
const GENERATOR_TYPE_SEQUENCE = 2;
/**
* TABLE means a separate table is used for id generation.
* Offers full portability.
*/
const GENERATOR_TYPE_TABLE = 3;
/**
* IDENTITY means an identity column is used for id generation. The database
* will fill in the id column on insertion. Platforms that do not support
@ -89,11 +95,13 @@ class ClassMetadataInfo implements ClassMetadata
* not guaranteed.
*/
const GENERATOR_TYPE_IDENTITY = 4;
/**
* NONE means the class does not have a generated id. That means the class
* must have a natural, manually assigned id.
*/
const GENERATOR_TYPE_NONE = 5;
/**
* UUID means that a UUID/GUID expression is used for id generation. Full
* portability is currently not guaranteed.
@ -111,53 +119,64 @@ class ClassMetadataInfo implements ClassMetadata
* This is the default change tracking policy.
*/
const CHANGETRACKING_DEFERRED_IMPLICIT = 1;
/**
* DEFERRED_EXPLICIT means that changes of entities are calculated at commit-time
* by doing a property-by-property comparison with the original data. This will
* be done only for entities that were explicitly saved (through persist() or a cascade).
*/
const CHANGETRACKING_DEFERRED_EXPLICIT = 2;
/**
* NOTIFY means that Doctrine relies on the entities sending out notifications
* when their properties change. Such entity classes must implement
* the <tt>NotifyPropertyChanged</tt> interface.
*/
const CHANGETRACKING_NOTIFY = 3;
/**
* Specifies that an association is to be fetched when it is first accessed.
*/
const FETCH_LAZY = 2;
/**
* Specifies that an association is to be fetched when the owner of the
* association is fetched.
*/
const FETCH_EAGER = 3;
/**
* Specifies that an association is to be fetched lazy (on first access) and that
* commands such as Collection#count, Collection#slice are issued directly against
* the database if the collection is not yet initialized.
*/
const FETCH_EXTRA_LAZY = 4;
/**
* Identifies a one-to-one association.
*/
const ONE_TO_ONE = 1;
/**
* Identifies a many-to-one association.
*/
const MANY_TO_ONE = 2;
/**
* Identifies a one-to-many association.
*/
const ONE_TO_MANY = 4;
/**
* Identifies a many-to-many association.
*/
const MANY_TO_MANY = 8;
/**
* Combined bitmask for to-one (single-valued) associations.
*/
const TO_ONE = 3;
/**
* Combined bitmask for to-many (collection-valued) associations.
*/
@ -237,6 +256,35 @@ class ClassMetadataInfo implements ClassMetadata
*/
public $namedQueries = array();
/**
* READ-ONLY: The named native queries allowed to be called directly from Repository.
*
* A native SQL named query definition has the following structure:
* <pre>
* array(
* 'name' => <query name>,
* 'query' => <sql query>,
* 'resultClass' => <class of the result>,
* 'resultSetMapping' => <name of a SqlResultSetMapping>
* )
* </pre>
*/
public $namedNativeQueries = array();
/**
* READ-ONLY: The mappings of the results of native SQL queries.
*
* A native result mapping definition has the following structure:
* <pre>
* array(
* 'name' => <result name>,
* 'entities' => array(<entity result mapping>),
* 'columns' => array(<column result mapping>)
* )
* </pre>
*/
public $sqlResultSetMappings = array();
/**
* READ-ONLY: The field names of all fields that are part of the identifier/primary key
* of the mapped entity class.
@ -748,6 +796,14 @@ class ClassMetadataInfo implements ClassMetadata
$serialized[] = 'namedQueries';
}
if ($this->namedNativeQueries) {
$serialized[] = 'namedNativeQueries';
}
if ($this->sqlResultSetMappings) {
$serialized[] = 'sqlResultSetMappings';
}
if ($this->isReadOnly) {
$serialized[] = 'isReadOnly';
}
@ -1051,6 +1107,60 @@ class ClassMetadataInfo implements ClassMetadata
return $this->namedQueries;
}
/**
* Gets the named native query.
*
* @see ClassMetadataInfo::$namedNativeQueries
* @throws MappingException
* @param string $queryName The query name
* @return array
*/
public function getNamedNativeQuery($queryName)
{
if ( ! isset($this->namedNativeQueries[$queryName])) {
throw MappingException::queryNotFound($this->name, $queryName);
}
return $this->namedNativeQueries[$queryName];
}
/**
* Gets all named native queries of the class.
*
* @return array
*/
public function getNamedNativeQueries()
{
return $this->namedNativeQueries;
}
/**
* Gets the result set mapping.
*
* @see ClassMetadataInfo::$sqlResultSetMappings
* @throws MappingException
* @param string $name The result set mapping name
* @return array
*/
public function getSqlResultSetMapping($name)
{
if ( ! isset($this->sqlResultSetMappings[$name])) {
throw MappingException::resultMappingNotFound($this->name, $name);
}
return $this->sqlResultSetMappings[$name];
}
/**
* Gets all sql result set mappings of the class.
*
* @return array
*/
public function getSqlResultSetMappings()
{
return $this->sqlResultSetMappings;
}
/**
* Validates & completes the given field mapping.
*
@ -1826,10 +1936,18 @@ class ClassMetadataInfo implements ClassMetadata
*/
public function addNamedQuery(array $queryMapping)
{
if (!isset($queryMapping['name'])) {
throw MappingException::nameIsMandatoryForQueryMapping($this->name);
}
if (isset($this->namedQueries[$queryMapping['name']])) {
throw MappingException::duplicateQueryMapping($this->name, $queryMapping['name']);
}
if (!isset($queryMapping['query'])) {
throw MappingException::emptyQueryMapping($this->name, $queryMapping['name']);
}
$name = $queryMapping['name'];
$query = $queryMapping['query'];
$dql = str_replace('__CLASS__', $this->name, $query);
@ -1840,6 +1958,107 @@ class ClassMetadataInfo implements ClassMetadata
);
}
/**
* INTERNAL:
* Adds a named native query to this class.
*
* @throws MappingException
* @param array $queryMapping
*/
public function addNamedNativeQuery(array $queryMapping)
{
if (!isset($queryMapping['name'])) {
throw MappingException::nameIsMandatoryForQueryMapping($this->name);
}
if (isset($this->namedNativeQueries[$queryMapping['name']])) {
throw MappingException::duplicateQueryMapping($this->name, $queryMapping['name']);
}
if (!isset($queryMapping['query'])) {
throw MappingException::emptyQueryMapping($this->name, $queryMapping['name']);
}
if (!isset($queryMapping['resultClass']) && !isset($queryMapping['resultSetMapping'])) {
throw MappingException::missingQueryMapping($this->name, $queryMapping['name']);
}
$queryMapping['isSelfClass'] = false;
if (isset($queryMapping['resultClass'])) {
if($queryMapping['resultClass'] === '__CLASS__') {
$queryMapping['isSelfClass'] = true;
$queryMapping['resultClass'] = $this->name;
} else if (strlen($this->namespace) > 0 && strpos($queryMapping['resultClass'], '\\') === false) {
$queryMapping['resultClass'] = $this->namespace . '\\' . $queryMapping['resultClass'];
}
$queryMapping['resultClass'] = ltrim($queryMapping['resultClass'], '\\');
}
$this->namedNativeQueries[$queryMapping['name']] = $queryMapping;
}
/**
* INTERNAL:
* Adds a sql result set mapping to this class.
*
* @throws MappingException
* @param array $resultMapping
*/
public function addSqlResultSetMapping(array $resultMapping)
{
if (!isset($resultMapping['name'])) {
throw MappingException::nameIsMandatoryForSqlResultSetMapping($this->name);
}
if (isset($this->sqlResultSetMappings[$resultMapping['name']])) {
throw MappingException::duplicateResultSetMapping($this->name, $resultMapping['name']);
}
if (isset($resultMapping['entities'])) {
foreach ($resultMapping['entities'] as $key => $entityResult) {
if (!isset($entityResult['entityClass'])) {
throw MappingException::missingResultSetMappingEntity($this->name, $resultMapping['name']);
}
$entityResult['isSelfClass'] = false;
if($entityResult['entityClass'] === '__CLASS__') {
$entityResult['isSelfClass'] = true;
$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'], '\\');
$resultMapping['entities'][$key]['isSelfClass'] = $entityResult['isSelfClass'];
if (isset($entityResult['fields'])) {
foreach ($entityResult['fields'] as $k => $field) {
if (!isset($field['name'])) {
throw MappingException::missingResultSetMappingFieldName($this->name, $resultMapping['name']);
}
if (!isset($field['column'])) {
$fieldName = $field['name'];
if(strpos($fieldName, '.')){
list(, $fieldName) = explode('.', $fieldName);
}
$resultMapping['entities'][$key]['fields'][$k]['column'] = $fieldName;
}
}
}
}
}
$this->sqlResultSetMappings[$resultMapping['name']] = $resultMapping;
}
/**
* Adds a one-to-one mapping.
*
@ -2053,7 +2272,7 @@ class ClassMetadataInfo implements ClassMetadata
/**
* Checks whether the class has a named query with the given query name.
*
* @param string $fieldName
* @param string $queryName
* @return boolean
*/
public function hasNamedQuery($queryName)
@ -2061,6 +2280,28 @@ class ClassMetadataInfo implements ClassMetadata
return isset($this->namedQueries[$queryName]);
}
/**
* Checks whether the class has a named native query with the given query name.
*
* @param string $queryName
* @return boolean
*/
public function hasNamedNativeQuery($queryName)
{
return isset($this->namedNativeQueries[$queryName]);
}
/**
* Checks whether the class has a named native query with the given query name.
*
* @param string $name
* @return boolean
*/
public function hasSqlResultSetMapping($name)
{
return isset($this->sqlResultSetMappings[$name]);
}
/**
* Checks whether the class has a mapped association with the given field name.
*
@ -2397,4 +2638,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

@ -0,0 +1,42 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Mapping;
/**
* References name of a column in the SELECT clause of a SQL query.
* Scalar result types can be included in the query result by specifying this annotation in the metadata.
*
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
* @since 2.3
*
* @Annotation
* @Target("ANNOTATION")
*/
final class ColumnResult implements Annotation
{
/**
* The name of a column in the SELECT clause of a SQL query
*
* @var string
*/
public $name;
}

View File

@ -204,6 +204,58 @@ 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();
$columns = 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;
}
foreach ($resultSetMapping->columns as $columnResultAnnot) {
$columns[] = array(
'name' => $columnResultAnnot->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'];

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

@ -85,6 +85,58 @@ class XmlDriver extends AbstractFileDriver
}
}
// Evaluate native named queries
if (isset($xmlRoot->{'named-native-queries'})) {
foreach ($xmlRoot->{'named-native-queries'}->{'named-native-query'} as $nativeQueryElement) {
$metadata->addNamedNativeQuery(array(
'name' => isset($nativeQueryElement['name']) ? (string)$nativeQueryElement['name'] : null,
'query' => isset($nativeQueryElement->query) ? (string)$nativeQueryElement->query : null,
'resultClass' => isset($nativeQueryElement['result-class']) ? (string)$nativeQueryElement['result-class'] : null,
'resultSetMapping' => isset($nativeQueryElement['result-set-mapping']) ? (string)$nativeQueryElement['result-set-mapping'] : null,
));
}
}
// Evaluate sql result set mapping
if (isset($xmlRoot->{'sql-result-set-mappings'})) {
foreach ($xmlRoot->{'sql-result-set-mappings'}->{'sql-result-set-mapping'} as $rsmElement) {
$entities = array();
$columns = array();
foreach ($rsmElement as $entityElement) {
//<entity-result/>
if (isset($entityElement['entity-class'])) {
$entityResult = array(
'fields' => array(),
'entityClass' => (string)$entityElement['entity-class'],
'discriminatorColumn' => isset($entityElement['discriminator-column']) ? (string)$entityElement['discriminator-column'] : null,
);
foreach ($entityElement as $fieldElement) {
$entityResult['fields'][] = array(
'name' => isset($fieldElement['name']) ? (string)$fieldElement['name'] : null,
'column' => isset($fieldElement['column']) ? (string)$fieldElement['column'] : null,
);
}
$entities[] = $entityResult;
}
//<column-result/>
if (isset($entityElement['name'])) {
$columns[] = array(
'name' => (string)$entityElement['name'],
);
}
}
$metadata->addSqlResultSetMapping(array(
'name' => (string)$rsmElement['name'],
'entities' => $entities,
'columns' => $columns
));
}
}
/* not implemented specially anyway. use table = schema.table
if (isset($xmlRoot['schema'])) {
$metadata->table['schema'] = (string)$xmlRoot['schema'];

View File

@ -83,6 +83,68 @@ class YamlDriver extends AbstractFileDriver
}
}
// Evaluate named native queries
if (isset($element['namedNativeQueries'])) {
foreach ($element['namedNativeQueries'] as $name => $mappingElement) {
if (!isset($mappingElement['name'])) {
$mappingElement['name'] = $name;
}
$metadata->addNamedNativeQuery(array(
'name' => $mappingElement['name'],
'query' => isset($mappingElement['query']) ? $mappingElement['query'] : null,
'resultClass' => isset($mappingElement['resultClass']) ? $mappingElement['resultClass'] : null,
'resultSetMapping' => isset($mappingElement['resultSetMapping']) ? $mappingElement['resultSetMapping'] : null,
));
}
}
// Evaluate sql result set mappings
if (isset($element['sqlResultSetMappings'])) {
foreach ($element['sqlResultSetMappings'] as $name => $resultSetMapping) {
if (!isset($resultSetMapping['name'])) {
$resultSetMapping['name'] = $name;
}
$entities = array();
$columns = array();
if (isset($resultSetMapping['entityResult'])) {
foreach ($resultSetMapping['entityResult'] as $entityResultElement) {
$entityResult = array(
'fields' => array(),
'entityClass' => isset($entityResultElement['entityClass']) ? $entityResultElement['entityClass'] : null,
'discriminatorColumn' => isset($entityResultElement['discriminatorColumn']) ? $entityResultElement['discriminatorColumn'] : null,
);
if (isset($entityResultElement['fieldResult'])) {
foreach ($entityResultElement['fieldResult'] as $fieldResultElement) {
$entityResult['fields'][] = array(
'name' => isset($fieldResultElement['name']) ? $fieldResultElement['name'] : null,
'column' => isset($fieldResultElement['column']) ? $fieldResultElement['column'] : null,
);
}
}
$entities[] = $entityResult;
}
}
if (isset($resultSetMapping['columnResult'])) {
foreach ($resultSetMapping['columnResult'] as $columnResultAnnot) {
$columns[] = array(
'name' => isset($columnResultAnnot['name']) ? $columnResultAnnot['name'] : null,
);
}
}
$metadata->addSqlResultSetMapping(array(
'name' => $resultSetMapping['name'],
'entities' => $entities,
'columns' => $columns
));
}
}
/* not implemented specially anyway. use table = schema.table
if (isset($element['schema'])) {
$metadata->table['schema'] = $element['schema'];
@ -484,10 +546,14 @@ class YamlDriver extends AbstractFileDriver
*/
private function _getJoinColumnMapping($joinColumnElement)
{
$joinColumn = array(
'name' => $joinColumnElement['name'],
'referencedColumnName' => $joinColumnElement['referencedColumnName']
);
$joinColumn = array();
if (isset($joinColumnElement['referencedColumnName'])) {
$joinColumn['referencedColumnName'] = (string) $joinColumnElement['referencedColumnName'];
}
if (isset($joinColumnElement['name'])) {
$joinColumn['name'] = (string) $joinColumnElement['name'];
}
if (isset($joinColumnElement['fieldName'])) {
$joinColumn['fieldName'] = (string) $joinColumnElement['fieldName'];

View File

@ -0,0 +1,58 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Mapping;
/**
* References an entity in the SELECT clause of a SQL query.
* If this annotation is used, the SQL statement should select all of the columns that are mapped to the entity object.
* This should include foreign key columns to related entities.
* The results obtained when insufficient data is available are undefined.
*
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
* @since 2.3
*
* @Annotation
* @Target("ANNOTATION")
*/
final class EntityResult implements Annotation
{
/**
* The class of the result
*
* @var string
*/
public $entityClass;
/**
* Maps the columns specified in the SELECT list of the query to the properties or fields of the entity class.
*
* @var array<\Doctrine\ORM\Mapping\FieldResult>
*/
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.
*
* @var string
*/
public $discriminatorColumn;
}

View File

@ -0,0 +1,48 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Mapping;
/**
* Is used to map the columns specified in the SELECT list of the query to the properties or fields of the entity class.
*
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
* @since 2.3
*
* @Annotation
* @Target("ANNOTATION")
*/
final class FieldResult implements Annotation
{
/**
* Name of the column in the SELECT clause.
*
* @var string
*/
public $name;
/**
* Name of the persistent field or property of the class.
*
* @var string
*/
public $column;
}

View File

@ -93,6 +93,41 @@ class MappingException extends \Doctrine\ORM\ORMException
return new self("No query found named '$queryName' on class '$className'.");
}
public static function resultMappingNotFound($className, $resultName)
{
return new self("No result set mapping found named '$resultName' on class '$className'.");
}
public static function emptyQueryMapping($entity, $queryName)
{
return new self('Query named "'.$queryName.'" in "'.$entity.'" could not be empty.');
}
public static function nameIsMandatoryForQueryMapping($className)
{
return new self("Query name on entity class '$className' is not defined.");
}
public static function missingQueryMapping($entity, $queryName)
{
return new self('Query named "'.$queryName.'" in "'.$entity.' requires a result class or result set mapping.');
}
public static function missingResultSetMappingEntity($entity, $resultName)
{
return new self('Result set mapping named "'.$resultName.'" in "'.$entity.' requires a entity class name.');
}
public static function missingResultSetMappingFieldName($entity, $resultName)
{
return new self('Result set mapping named "'.$resultName.'" in "'.$entity.' requires a field name.');
}
public static function nameIsMandatoryForSqlResultSetMapping($className)
{
return new self("Result set mapping name on entity class '$className' is not defined.");
}
public static function oneToManyRequiresMappedBy($fieldName)
{
return new self("OneToMany mapping on field '$fieldName' requires the 'mappedBy' attribute.");
@ -178,27 +213,36 @@ class MappingException extends \Doctrine\ORM\ORMException
}
/**
*
* @param string $entity The entity's name
* @param string $fieldName The name of the field that was already declared
*/
public static function duplicateFieldMapping($entity, $fieldName) {
public static function duplicateFieldMapping($entity, $fieldName)
{
return new self('Property "'.$fieldName.'" in "'.$entity.'" was already declared, but it must be declared only once');
}
public static function duplicateAssociationMapping($entity, $fieldName) {
public static function duplicateAssociationMapping($entity, $fieldName)
{
return new self('Property "'.$fieldName.'" in "'.$entity.'" was already declared, but it must be declared only once');
}
public static function duplicateQueryMapping($entity, $queryName) {
public static function duplicateQueryMapping($entity, $queryName)
{
return new self('Query named "'.$queryName.'" in "'.$entity.'" was already declared, but it must be declared only once');
}
public static function singleIdNotAllowedOnCompositePrimaryKey($entity) {
public static function duplicateResultSetMapping($entity, $resultName)
{
return new self('Result set mapping named "'.$resultName.'" in "'.$entity.'" was already declared, but it must be declared only once');
}
public static function singleIdNotAllowedOnCompositePrimaryKey($entity)
{
return new self('Single id is not allowed on composite primary key in entity '.$entity);
}
public static function unsupportedOptimisticLockingType($entity, $fieldName, $unsupportedType) {
public static function unsupportedOptimisticLockingType($entity, $fieldName, $unsupportedType)
{
return new self('Locking type "'.$unsupportedType.'" (specified in "'.$entity.'", field "'.$fieldName.'") '
.'is not supported by Doctrine.'
);
@ -224,7 +268,8 @@ class MappingException extends \Doctrine\ORM\ORMException
* @param string $owningClass The class that declares the discriminator map.
* @return self
*/
public static function invalidClassInDiscriminatorMap($className, $owningClass) {
public static function invalidClassInDiscriminatorMap($className, $owningClass)
{
return new self(
"Entity class '$className' used in the discriminator map of class '$owningClass' ".
"does not exist."

View File

@ -0,0 +1,40 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Mapping;
/**
* Is used to specify an array of native SQL named queries.
* The NamedNativeQueries annotation can be applied to an entity or mapped superclass.
*
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
* @since 2.3
*
* @Annotation
* @Target("CLASS")
*/
final class NamedNativeQueries implements Annotation
{
/**
* One or more NamedNativeQuery annotations.
*
* @var array<\Doctrine\ORM\Mapping\NamedNativeQuery>
*/
public $value = array();
}

View File

@ -0,0 +1,63 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Mapping;
/**
* Is used to specify a native SQL named query.
* The NamedNativeQuery annotation can be applied to an entity or mapped superclass.
*
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
* @since 2.3
*
* @Annotation
* @Target("ANNOTATION")
*/
final class NamedNativeQuery implements Annotation
{
/**
* The name used to refer to the query with the EntityManager methods that create query objects.
*
* @var string
*/
public $name;
/**
* The SQL query string.
*
* @var string
*/
public $query;
/**
* The class of the result.
*
* @var string
*/
public $resultClass;
/**
* The name of a SqlResultSetMapping, as defined in metadata.
*
* @var string
*/
public $resultSetMapping;
}

View File

@ -0,0 +1,56 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Mapping;
/**
* The SqlResultSetMapping annotation is used to specify the mapping of the result of a native SQL query.
* The SqlResultSetMapping annotation can be applied to an entity or mapped superclass.
*
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
* @since 2.3
*
* @Annotation
* @Target("ANNOTATION")
*/
final class SqlResultSetMapping implements Annotation
{
/**
* The name given to the result set mapping, and used to refer to it in the methods of the Query API.
*
* @var string
*/
public $name;
/**
* Specifies the result set mapping to entities.
*
* @var array<\Doctrine\ORM\Mapping\EntityResult>
*/
public $entities = array();
/**
* Specifies the result set mapping to scalar values.
*
* @var array<\Doctrine\ORM\Mapping\ColumnResult>
*/
public $columns = array();
}

View File

@ -0,0 +1,40 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Mapping;
/**
* Is used to specify an array of mappings.
* The SqlResultSetMappings annotation can be applied to an entity or mapped superclass.
*
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
* @since 2.3
*
* @Annotation
* @Target("CLASS")
*/
final class SqlResultSetMappings implements Annotation
{
/**
* One or more SqlResultSetMapping annotations.
*
* @var array<\Doctrine\ORM\Mapping\SqlResultSetMapping>
*/
public $value = array();
}

View File

@ -106,4 +106,159 @@ class ResultSetMappingBuilder extends ResultSetMapping
}
}
}
}
/**
* Adds the mappings of the results of native SQL queries to the result set.
*
* @param ClassMetadataInfo $class
* @param array $queryMapping
* @return ResultSetMappingBuilder
*/
public function addNamedNativeQueryMapping(ClassMetadataInfo $class, array $queryMapping)
{
if (isset($queryMapping['resultClass'])) {
return $this->addNamedNativeQueryResultClassMapping($class, $queryMapping['resultClass']);
}
return $this->addNamedNativeQueryResultSetMapping($class, $queryMapping['resultSetMapping']);
}
/**
* Adds the class mapping of the results of native SQL queries to the result set.
*
* @param ClassMetadataInfo $class
* @param string $resultClassName
* @return ResultSetMappingBuilder
*/
public function addNamedNativeQueryResultClassMapping(ClassMetadataInfo $class, $resultClassName)
{
$classMetadata = $this->em->getClassMetadata($resultClassName);
$shortName = $classMetadata->reflClass->getShortName();
$alias = strtolower($shortName[0]).'0';
$this->addEntityResult($class->name, $alias);
if ($classMetadata->discriminatorColumn) {
$discriminatorColumn = $classMetadata->discriminatorColumn;
$this->setDiscriminatorColumn($alias, $discriminatorColumn['name']);
$this->addMetaResult($alias, $discriminatorColumn['name'], $discriminatorColumn['fieldName']);
}
foreach ($classMetadata->getColumnNames() as $key => $columnName) {
$propertyName = $classMetadata->getFieldName($columnName);
$this->addFieldResult($alias, $columnName, $propertyName);
}
foreach ($classMetadata->associationMappings as $associationMapping) {
if ($associationMapping['isOwningSide'] && $associationMapping['type'] & ClassMetadataInfo::TO_ONE) {
foreach ($associationMapping['joinColumns'] as $joinColumn) {
$columnName = $joinColumn['name'];
$this->addMetaResult($alias, $columnName, $columnName, $classMetadata->isIdentifier($columnName));
}
}
}
return $this;
}
/**
* Adds the result set mapping of the results of native SQL queries to the result set.
*
* @param ClassMetadataInfo $class
* @param string $resultSetMappingName
* @return ResultSetMappingBuilder
*/
public function addNamedNativeQueryResultSetMapping(ClassMetadataInfo $class, $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']);
if ($class->reflClass->name == $classMetadata->reflClass->name) {
$this->addEntityResult($classMetadata->name, $rootAlias);
$this->addNamedNativeQueryEntityResultMapping($classMetadata, $entityMapping, $rootAlias);
} else {
$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);
}
}
}
}
if (isset($resultMapping['columns'])) {
foreach ($resultMapping['columns'] as $entityMapping) {
$this->addScalarResult($entityMapping['name'], $entityMapping['name']);
}
}
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

@ -8,6 +8,57 @@ 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"
* ),
* @NamedNativeQuery(
* name = "find-by-id",
* resultClass = "CmsAddress",
* query = "SELECT * FROM cms_addresses WHERE id = ?"
* ),
* @NamedNativeQuery(
* name = "count",
* resultSetMapping= "mapping-count",
* query = "SELECT COUNT(*) AS count 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")
* }
* )
* }
* ),
* @SqlResultSetMapping(
* name = "mapping-without-fields",
* entities= {
* @EntityResult(
* entityClass = "__CLASS__"
* )
* }
* ),
* @SqlResultSetMapping(
* name = "mapping-count",
* columns = {
* @ColumnResult(
* name = "count"
* )
* }
* )
* })
*
*/
class CmsAddress
{
@ -69,4 +120,72 @@ class CmsAddress
$user->setAddress($this);
}
}
public static function loadMetadata(\Doctrine\ORM\Mapping\ClassMetadataInfo $metadata)
{
$metadata->setPrimaryTable(array(
'name' => 'company_person',
));
$metadata->addNamedNativeQuery(array (
'name' => 'find-all',
'query' => 'SELECT id, country, city FROM cms_addresses',
'resultSetMapping' => 'mapping-find-all',
));
$metadata->addNamedNativeQuery(array (
'name' => 'find-by-id',
'query' => 'SELECT * FROM cms_addresses WHERE id = ?',
'resultClass' => 'Doctrine\\Tests\\Models\\CMS\\CmsAddress',
));
$metadata->addNamedNativeQuery(array (
'name' => 'count',
'query' => 'SELECT COUNT(*) AS count FROM cms_addresses',
'resultSetMapping' => 'mapping-count',
));
$metadata->addSqlResultSetMapping(array (
'name' => 'mapping-find-all',
'columns' => array(),
'entities' => array ( array (
'fields' => array (
array (
'name' => 'id',
'column' => 'id',
),
array (
'name' => 'city',
'column' => 'city',
),
array (
'name' => 'country',
'column' => 'country',
),
),
'entityClass' => 'Doctrine\Tests\Models\CMS\CmsAddress',
),
),
));
$metadata->addSqlResultSetMapping(array (
'name' => 'mapping-without-fields',
'columns' => array(),
'entities' => array(array (
'entityClass' => 'Doctrine\\Tests\\Models\\CMS\\CmsAddress',
'fields' => array()
)
)
));
$metadata->addSqlResultSetMapping(array (
'name' => 'mapping-count',
'columns' =>array (
array (
'name' => 'count',
),
)
));
}
}

View File

@ -10,6 +10,113 @@ use Doctrine\Common\Collections\ArrayCollection;
* @NamedQueries({
* @NamedQuery(name="all", query="SELECT u FROM __CLASS__ u")
* })
*
* @NamedNativeQueries({
* @NamedNativeQuery(
* name = "fetchIdAndUsernameWithResultClass",
* resultClass = "CmsUser",
* query = "SELECT id, username FROM cms_users WHERE username = ?"
* ),
* @NamedNativeQuery(
* name = "fetchAllColumns",
* resultClass = "CmsUser",
* query = "SELECT * FROM cms_users WHERE username = ?"
* ),
* @NamedNativeQuery(
* name = "fetchJoinedAddress",
* resultSetMapping= "mappingJoinedAddress",
* query = "SELECT u.id, u.name, u.status, a.id AS a_id, a.country, a.zip, a.city FROM cms_users u INNER JOIN cms_addresses a ON u.id = a.user_id WHERE u.username = ?"
* ),
* @NamedNativeQuery(
* name = "fetchJoinedPhonenumber",
* resultSetMapping= "mappingJoinedPhonenumber",
* query = "SELECT id, name, status, phonenumber AS number FROM cms_users INNER JOIN cms_phonenumbers ON id = user_id WHERE username = ?"
* ),
* @NamedNativeQuery(
* 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"
* ),
* @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({
* @SqlResultSetMapping(
* name = "mappingJoinedAddress",
* entities= {
* @EntityResult(
* entityClass = "__CLASS__",
* fields = {
* @FieldResult(name = "id"),
* @FieldResult(name = "name"),
* @FieldResult(name = "status"),
* @FieldResult(name = "address.zip"),
* @FieldResult(name = "address.city"),
* @FieldResult(name = "address.country"),
* @FieldResult(name = "address.id", column = "a_id"),
* }
* )
* }
* ),
* @SqlResultSetMapping(
* name = "mappingJoinedPhonenumber",
* entities= {
* @EntityResult(
* entityClass = "CmsUser",
* fields = {
* @FieldResult("id"),
* @FieldResult("name"),
* @FieldResult("status"),
* @FieldResult("phonenumbers.phonenumber" , column = "number"),
* }
* )
* }
* ),
* @SqlResultSetMapping(
* name = "mappingUserPhonenumberCount",
* entities= {
* @EntityResult(
* entityClass = "CmsUser",
* fields = {
* @FieldResult(name = "id"),
* @FieldResult(name = "name"),
* @FieldResult(name = "status"),
* }
* )
* },
* 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")
* }
* )
* })
*/
class CmsUser
{
@ -140,4 +247,191 @@ class CmsUser
}
}
}
public static function loadMetadata(\Doctrine\ORM\Mapping\ClassMetadataInfo $metadata)
{
$metadata->setPrimaryTable(array(
'name' => 'cms_users',
));
$metadata->addNamedNativeQuery(array (
'name' => 'fetchIdAndUsernameWithResultClass',
'query' => 'SELECT id, username FROM cms_users WHERE username = ?',
'resultClass' => 'Doctrine\\Tests\\Models\\CMS\\CmsUser',
));
$metadata->addNamedNativeQuery(array (
'name' => 'fetchAllColumns',
'query' => 'SELECT * FROM cms_users WHERE username = ?',
'resultClass' => 'Doctrine\\Tests\\Models\\CMS\\CmsUser',
));
$metadata->addNamedNativeQuery(array (
'name' => 'fetchJoinedAddress',
'query' => 'SELECT u.id, u.name, u.status, a.id AS a_id, a.country, a.zip, a.city FROM cms_users u INNER JOIN cms_addresses a ON u.id = a.user_id WHERE u.username = ?',
'resultSetMapping' => 'mappingJoinedAddress',
));
$metadata->addNamedNativeQuery(array (
'name' => 'fetchJoinedPhonenumber',
'query' => 'SELECT id, name, status, phonenumber AS number FROM cms_users INNER JOIN cms_phonenumbers ON id = user_id WHERE username = ?',
'resultSetMapping' => 'mappingJoinedPhonenumber',
));
$metadata->addNamedNativeQuery(array (
'name' => 'fetchUserPhonenumberCount',
'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',
'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(),
'entities' => array(array (
'fields'=> array (
array (
'name' => 'id',
'column' => 'id',
),
array (
'name' => 'name',
'column' => 'name',
),
array (
'name' => 'status',
'column' => 'status',
),
array (
'name' => 'address.zip',
'column' => 'zip',
),
array (
'name' => 'address.city',
'column' => 'city',
),
array (
'name' => 'address.country',
'column' => 'country',
),
array (
'name' => 'address.id',
'column' => 'a_id',
),
),
'entityClass' => 'Doctrine\Tests\Models\CMS\CmsUser',
'discriminatorColumn' => null
),
),
));
$metadata->addSqlResultSetMapping(array (
'name' => 'mappingJoinedPhonenumber',
'columns' => array(),
'entities' => array(array(
'fields'=> array (
array (
'name' => 'id',
'column' => 'id',
),
array (
'name' => 'name',
'column' => 'name',
),
array (
'name' => 'status',
'column' => 'status',
),
array (
'name' => 'phonenumbers.phonenumber',
'column' => 'number',
),
),
'entityClass' => 'Doctrine\\Tests\\Models\\CMS\\CmsUser',
'discriminatorColumn' => null
),
),
));
$metadata->addSqlResultSetMapping(array (
'name' => 'mappingUserPhonenumberCount',
'columns' => array(),
'entities' => array (
array(
'fields' => array (
array (
'name' => 'id',
'column' => 'id',
),
array (
'name' => 'name',
'column' => 'name',
),
array (
'name' => 'status',
'column' => 'status',
)
),
'entityClass' => 'Doctrine\Tests\Models\CMS\CmsUser',
'discriminatorColumn' => null
)
),
'columns' => array (
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

@ -12,6 +12,48 @@ namespace Doctrine\Tests\Models\Company;
* "flexible" = "CompanyFlexContract",
* "flexultra" = "CompanyFlexUltraContract"
* })
*
* @NamedNativeQueries({
* @NamedNativeQuery(
* name = "all-contracts",
* resultClass = "__CLASS__",
* query = "SELECT id, completed, discr FROM company_contracts"
* ),
* @NamedNativeQuery(
* name = "all",
* resultClass = "__CLASS__",
* query = "SELECT id, completed, discr FROM company_contracts"
* ),
* })
*
* @SqlResultSetMappings({
* @SqlResultSetMapping(
* name = "mapping-all-contracts",
* entities= {
* @EntityResult(
* entityClass = "__CLASS__",
* discriminatorColumn = "discr",
* fields = {
* @FieldResult("id"),
* @FieldResult("completed"),
* }
* )
* }
* ),
* @SqlResultSetMapping(
* name = "mapping-all",
* entities= {
* @EntityResult(
* entityClass = "__CLASS__",
* discriminatorColumn = "discr",
* fields = {
* @FieldResult("id"),
* @FieldResult("completed"),
* }
* )
* }
* ),
* })
*/
abstract class CompanyContract
{

View File

@ -3,6 +3,48 @@ namespace Doctrine\Tests\Models\Company;
/**
* @Entity
*
* @NamedNativeQueries({
* @NamedNativeQuery(
* name = "all",
* resultClass = "__CLASS__",
* query = "SELECT id, hoursWorked, discr FROM company_contracts"
* ),
* @NamedNativeQuery(
* name = "all-flex",
* resultClass = "CompanyFlexContract",
* query = "SELECT id, hoursWorked, discr FROM company_contracts"
* ),
* })
*
* @SqlResultSetMappings({
* @SqlResultSetMapping(
* name = "mapping-all-flex",
* entities= {
* @EntityResult(
* entityClass = "__CLASS__",
* discriminatorColumn = "discr",
* fields = {
* @FieldResult("id"),
* @FieldResult("hoursWorked"),
* }
* )
* }
* ),
* @SqlResultSetMapping(
* name = "mapping-all",
* entities= {
* @EntityResult(
* entityClass = "CompanyFlexContract",
* discriminatorColumn = "discr",
* fields = {
* @FieldResult("id"),
* @FieldResult("hoursWorked"),
* }
* )
* }
* ),
* })
*/
class CompanyFlexContract extends CompanyContract
{

View File

@ -11,9 +11,39 @@ namespace Doctrine\Tests\Models\Company;
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({
* "person" = "CompanyPerson",
* "manager" = "CompanyManager",
* "employee" = "CompanyEmployee"})
* "person" = "CompanyPerson",
* "manager" = "CompanyManager",
* "employee" = "CompanyEmployee"
* })
*
* @NamedNativeQueries({
* @NamedNativeQuery(
* name = "fetchAllWithResultClass",
* resultClass = "__CLASS__",
* query = "SELECT id, name, discr FROM company_persons ORDER BY name"
* ),
* @NamedNativeQuery(
* name = "fetchAllWithSqlResultSetMapping",
* resultSetMapping= "mappingFetchAll",
* query = "SELECT id, name, discr AS discriminator FROM company_persons ORDER BY name"
* )
* })
*
* @SqlResultSetMappings({
* @SqlResultSetMapping(
* name = "mappingFetchAll",
* entities= {
* @EntityResult(
* entityClass = "__CLASS__",
* discriminatorColumn = "discriminator",
* fields = {
* @FieldResult("id"),
* @FieldResult("name"),
* }
* )
* }
* )
* })
*/
class CompanyPerson
{
@ -78,5 +108,45 @@ class CompanyPerson
$this->spouse->setSpouse($this);
}
}
public static function loadMetadata(\Doctrine\ORM\Mapping\ClassMetadataInfo $metadata)
{
$metadata->setPrimaryTable(array(
'name' => 'company_person',
));
$metadata->addNamedNativeQuery(array (
'name' => 'fetchAllWithResultClass',
'query' => 'SELECT id, name, discr FROM company_persons ORDER BY name',
'resultClass' => 'Doctrine\\Tests\\Models\\Company\\CompanyPerson',
));
$metadata->addNamedNativeQuery(array (
'name' => 'fetchAllWithSqlResultSetMapping',
'query' => 'SELECT id, name, discr AS discriminator FROM company_persons ORDER BY name',
'resultSetMapping' => 'mappingFetchAll',
));
$metadata->addSqlResultSetMapping(array (
'name' => 'mappingFetchAll',
'columns' => array(),
'entities' => array ( array (
'fields' => array (
array (
'name' => 'id',
'column' => 'id',
),
array (
'name' => 'name',
'column' => 'name',
),
),
'entityClass' => 'Doctrine\Tests\Models\Company\CompanyPerson',
'discriminatorColumn' => 'discriminator',
),
),
));
}
}

View File

@ -7,8 +7,11 @@ 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\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;
require_once __DIR__ . '/../../TestInit.php';
@ -23,6 +26,7 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
protected function setUp() {
$this->useModelSet('cms');
$this->useModelSet('company');
parent::setUp();
$this->platform = $this->_em->getConnection()->getDatabasePlatform();
}
@ -329,5 +333,372 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
);
$users = $query->getResult();
}
}
/**
* @group DDC-1663
*/
public function testBasicNativeNamedQueryWithSqlResultSetMapping()
{
$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);
}
/**
* @group DDC-1663
*/
public function testBasicNativeNamedQueryWithResultClass()
{
$user = new CmsUser;
$user->name = 'Fabio B. Silva';
$user->username = 'FabioBatSilva';
$user->status = 'dev';
$email = new CmsEmail();
$email->email = 'fabio.bat.silva@gmail.com';
$user->setEmail($email);
$this->_em->clear();
$this->_em->persist($user);
$this->_em->flush();
$this->_em->clear();
$repository = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser');
$result = $repository->createNativeNamedQuery('fetchIdAndUsernameWithResultClass')
->setParameter(1, 'FabioBatSilva')->getResult();
$this->assertEquals(1, count($result));
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $result[0]);
$this->assertNull($result[0]->name);
$this->assertNull($result[0]->email);
$this->assertEquals($user->id, $result[0]->id);
$this->assertEquals('FabioBatSilva', $result[0]->username);
$this->_em->clear();
$result = $repository->createNativeNamedQuery('fetchAllColumns')
->setParameter(1, 'FabioBatSilva')->getResult();
$this->assertEquals(1, count($result));
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $result[0]);
$this->assertEquals($user->id, $result[0]->id);
$this->assertEquals('Fabio B. Silva', $result[0]->name);
$this->assertEquals('FabioBatSilva', $result[0]->username);
$this->assertEquals('dev', $result[0]->status);
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsEmail', $result[0]->email);
}
/**
* @group DDC-1663
*/
public function testJoinedOneToOneNativeNamedQueryWithResultSetMapping()
{
$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->persist($user);
$this->_em->flush();
$this->_em->clear();
$repository = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser');
$result = $repository->createNativeNamedQuery('fetchJoinedAddress')
->setParameter(1, 'FabioBatSilva')->getResult();
$this->assertEquals(1, count($result));
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $result[0]);
$this->assertEquals('Fabio B. Silva', $result[0]->name);
$this->assertInstanceOf('Doctrine\ORM\PersistentCollection', $result[0]->getPhonenumbers());
$this->assertFalse($result[0]->getPhonenumbers()->isInitialized());
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsAddress', $result[0]->getAddress());
$this->assertTrue($result[0]->getAddress()->getUser() == $result[0]);
$this->assertEquals('Brazil', $result[0]->getAddress()->getCountry());
$this->assertEquals(10827, $result[0]->getAddress()->getZipCode());
$this->assertEquals('São Paulo', $result[0]->getAddress()->getCity());
}
/**
* @group DDC-1663
*/
public function testJoinedOneToManyNativeNamedQueryWithResultSetMapping()
{
$user = new CmsUser;
$user->name = 'Fabio B. Silva';
$user->username = 'FabioBatSilva';
$user->status = 'dev';
$phone = new CmsPhonenumber;
$phone->phonenumber = 424242;
$user->addPhonenumber($phone);
$this->_em->persist($user);
$this->_em->flush();
$this->_em->clear();
$repository = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser');
$result = $repository->createNativeNamedQuery('fetchJoinedPhonenumber')
->setParameter(1, 'FabioBatSilva')->getResult();
$this->assertEquals(1, count($result));
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $result[0]);
$this->assertEquals('Fabio B. Silva', $result[0]->name);
$this->assertInstanceOf('Doctrine\ORM\PersistentCollection', $result[0]->getPhonenumbers());
$this->assertTrue($result[0]->getPhonenumbers()->isInitialized());
$this->assertEquals(1, count($result[0]->getPhonenumbers()));
$phones = $result[0]->getPhonenumbers();
$this->assertEquals(424242, $phones[0]->phonenumber);
$this->assertTrue($phones[0]->getUser() === $result[0]);
}
/**
* @group DDC-1663
*/
public function testMixedNativeNamedQueryNormalJoin()
{
$user1 = new CmsUser;
$user1->name = 'Fabio B. Silva';
$user1->username = 'FabioBatSilva';
$user1->status = 'dev';
$user2 = new CmsUser;
$user2->name = 'test tester';
$user2->username = 'test';
$user2->status = 'tester';
$phone1 = new CmsPhonenumber;
$phone2 = new CmsPhonenumber;
$phone3 = new CmsPhonenumber;
$phone1->phonenumber = 11111111;
$phone2->phonenumber = 22222222;
$phone3->phonenumber = 33333333;
$user1->addPhonenumber($phone1);
$user1->addPhonenumber($phone2);
$user2->addPhonenumber($phone3);
$this->_em->persist($user1);
$this->_em->persist($user2);
$this->_em->flush();
$this->_em->clear();
$repository = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser');
$result = $repository->createNativeNamedQuery('fetchUserPhonenumberCount')
->setParameter(1, array('test','FabioBatSilva'))->getResult();
$this->assertEquals(2, count($result));
$this->assertTrue(is_array($result[0]));
$this->assertTrue(is_array($result[1]));
// first user => 2 phonenumbers
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $result[0][0]);
$this->assertEquals('Fabio B. Silva', $result[0][0]->name);
$this->assertEquals(2, $result[0]['numphones']);
// second user => 1 phonenumbers
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $result[1][0]);
$this->assertEquals('test tester', $result[1][0]->name);
$this->assertEquals(1, $result[1]['numphones']);
}
/**
* @group DDC-1663
*/
public function testNativeNamedQueryInheritance()
{
$person = new CompanyPerson;
$person->setName('Fabio B. Silva');
$employee = new CompanyEmployee;
$employee->setName('Fabio Silva');
$employee->setSalary(100000);
$employee->setDepartment('IT');
$this->_em->persist($person);
$this->_em->persist($employee);
$this->_em->flush();
$this->_em->clear();
$repository = $this->_em->getRepository('Doctrine\Tests\Models\Company\CompanyPerson');
$result = $repository->createNativeNamedQuery('fetchAllWithSqlResultSetMapping')
->getResult();
$this->assertEquals(2, count($result));
$this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyPerson', $result[0]);
$this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyEmployee', $result[1]);
$this->assertTrue(is_numeric($result[0]->getId()));
$this->assertTrue(is_numeric($result[1]->getId()));
$this->assertEquals('Fabio B. Silva', $result[0]->getName());
$this->assertEquals('Fabio Silva', $result[1]->getName());
$this->_em->clear();
$result = $repository->createNativeNamedQuery('fetchAllWithResultClass')
->getResult();
$this->assertEquals(2, count($result));
$this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyPerson', $result[0]);
$this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyEmployee', $result[1]);
$this->assertTrue(is_numeric($result[0]->getId()));
$this->assertTrue(is_numeric($result[1]->getId()));
$this->assertEquals('Fabio B. Silva', $result[0]->getName());
$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']);
}
/**
* @group DDC-1663
*/
public function testNamedNativeQueryInheritance()
{
$contractMetadata = $this->_em->getClassMetadata('Doctrine\Tests\Models\Company\CompanyContract');
$flexMetadata = $this->_em->getClassMetadata('Doctrine\Tests\Models\Company\CompanyFlexContract');
$contractQueries = $contractMetadata->getNamedNativeQueries();
$flexQueries = $flexMetadata->getNamedNativeQueries();
$contractMappings = $contractMetadata->getSqlResultSetMappings();
$flexMappings = $flexMetadata->getSqlResultSetMappings();
// contract queries
$this->assertEquals('all-contracts', $contractQueries['all-contracts']['name']);
$this->assertEquals('Doctrine\Tests\Models\Company\CompanyContract', $contractQueries['all-contracts']['resultClass']);
$this->assertEquals('all', $contractQueries['all']['name']);
$this->assertEquals('Doctrine\Tests\Models\Company\CompanyContract', $contractQueries['all']['resultClass']);
// flex contract queries
$this->assertEquals('all-contracts', $flexQueries['all-contracts']['name']);
$this->assertEquals('Doctrine\Tests\Models\Company\CompanyFlexContract', $flexQueries['all-contracts']['resultClass']);
$this->assertEquals('all-flex', $flexQueries['all-flex']['name']);
$this->assertEquals('Doctrine\Tests\Models\Company\CompanyFlexContract', $flexQueries['all-flex']['resultClass']);
$this->assertEquals('all', $flexQueries['all']['name']);
$this->assertEquals('Doctrine\Tests\Models\Company\CompanyFlexContract', $flexQueries['all']['resultClass']);
// contract result mapping
$this->assertEquals('mapping-all-contracts', $contractMappings['mapping-all-contracts']['name']);
$this->assertEquals('Doctrine\Tests\Models\Company\CompanyContract', $contractMappings['mapping-all-contracts']['entities'][0]['entityClass']);
$this->assertEquals('mapping-all', $contractMappings['mapping-all']['name']);
$this->assertEquals('Doctrine\Tests\Models\Company\CompanyContract', $contractMappings['mapping-all-contracts']['entities'][0]['entityClass']);
// flex contract result mapping
$this->assertEquals('mapping-all-contracts', $flexMappings['mapping-all-contracts']['name']);
$this->assertEquals('Doctrine\Tests\Models\Company\CompanyFlexContract', $flexMappings['mapping-all-contracts']['entities'][0]['entityClass']);
$this->assertEquals('mapping-all', $flexMappings['mapping-all']['name']);
$this->assertEquals('Doctrine\Tests\Models\Company\CompanyFlexContract', $flexMappings['mapping-all']['entities'][0]['entityClass']);
$this->assertEquals('mapping-all-flex', $flexMappings['mapping-all-flex']['name']);
$this->assertEquals('Doctrine\Tests\Models\Company\CompanyFlexContract', $flexMappings['mapping-all-flex']['entities'][0]['entityClass']);
}
}

View File

@ -93,5 +93,167 @@ class ResultSetMappingTest extends \Doctrine\Tests\OrmTestCase
$this->assertTrue($rms->hasParentAlias('p'));
$this->assertTrue($rms->isMixedResult());
}
/**
* @group DDC-1663
*/
public function testAddNamedNativeQueryResultSetMapping()
{
$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',
'resultSetMapping' => 'find-all',
));
$cm->addSqlResultSetMapping(array(
'name' => 'find-all',
'entities' => array(
array(
'entityClass' => '__CLASS__',
'fields' => array(
array(
'name' => 'id',
'column'=> 'user_id'
),
array(
'name' => 'name',
'column'=> 'name'
)
)
),
array(
'entityClass' => 'CmsEmail',
'fields' => array(
array(
'name' => 'id',
'column'=> 'email_id'
),
array(
'name' => 'email',
'column'=> 'email'
)
)
)
),
'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('user_id'));
$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('c1', $rsm->getEntityAlias('email_id'));
$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'));
}
/**
* @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'));
}
}

View File

@ -467,6 +467,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
}
/**
<<<<<<< HEAD
* @group DDC-889
* @expectedException Doctrine\ORM\Mapping\MappingException
* @expectedExceptionMessage Class "Doctrine\Tests\Models\DDC889\DDC889Class" sub class of "Doctrine\Tests\Models\DDC889\DDC889SuperClass" is not a valid entity or mapped super class.
@ -488,6 +489,130 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
$factory->getMetadataFor('Doctrine\Tests\Models\DDC889\DDC889Entity');
}
/**
* @group DDC-1663
*/
public function testNamedNativeQuery()
{
$class = $this->createClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress');
//named native query
$this->assertCount(3, $class->namedNativeQueries);
$this->assertArrayHasKey('find-all', $class->namedNativeQueries);
$this->assertArrayHasKey('find-by-id', $class->namedNativeQueries);
$findAllQuery = $class->getNamedNativeQuery('find-all');
$this->assertEquals('find-all', $findAllQuery['name']);
$this->assertEquals('mapping-find-all', $findAllQuery['resultSetMapping']);
$this->assertEquals('SELECT id, country, city FROM cms_addresses', $findAllQuery['query']);
$findByIdQuery = $class->getNamedNativeQuery('find-by-id');
$this->assertEquals('find-by-id', $findByIdQuery['name']);
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsAddress',$findByIdQuery['resultClass']);
$this->assertEquals('SELECT * FROM cms_addresses WHERE id = ?', $findByIdQuery['query']);
$countQuery = $class->getNamedNativeQuery('count');
$this->assertEquals('count', $countQuery['name']);
$this->assertEquals('mapping-count', $countQuery['resultSetMapping']);
$this->assertEquals('SELECT COUNT(*) AS count FROM cms_addresses', $countQuery['query']);
// result set mapping
$this->assertCount(3, $class->sqlResultSetMappings);
$this->assertArrayHasKey('mapping-count', $class->sqlResultSetMappings);
$this->assertArrayHasKey('mapping-find-all', $class->sqlResultSetMappings);
$this->assertArrayHasKey('mapping-without-fields', $class->sqlResultSetMappings);
$findAllMapping = $class->getSqlResultSetMapping('mapping-find-all');
$this->assertEquals('mapping-find-all', $findAllMapping['name']);
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsAddress', $findAllMapping['entities'][0]['entityClass']);
$this->assertEquals(array('name'=>'id','column'=>'id'), $findAllMapping['entities'][0]['fields'][0]);
$this->assertEquals(array('name'=>'city','column'=>'city'), $findAllMapping['entities'][0]['fields'][1]);
$this->assertEquals(array('name'=>'country','column'=>'country'), $findAllMapping['entities'][0]['fields'][2]);
$withoutFieldsMapping = $class->getSqlResultSetMapping('mapping-without-fields');
$this->assertEquals('mapping-without-fields', $withoutFieldsMapping['name']);
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsAddress', $withoutFieldsMapping['entities'][0]['entityClass']);
$this->assertEquals(array(), $withoutFieldsMapping['entities'][0]['fields']);
$countMapping = $class->getSqlResultSetMapping('mapping-count');
$this->assertEquals('mapping-count', $countMapping['name']);
$this->assertEquals(array('name'=>'count'), $countMapping['columns'][0]);
}
/**
* @group DDC-1663
*/
public function testSqlResultSetMapping()
{
$userMetadata = $this->createClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$personMetadata = $this->createClassMetadata('Doctrine\Tests\Models\Company\CompanyPerson');
// user asserts
$this->assertCount(4, $userMetadata->getSqlResultSetMappings());
$mapping = $userMetadata->getSqlResultSetMapping('mappingJoinedAddress');
$this->assertEquals(array(),$mapping['columns']);
$this->assertEquals('mappingJoinedAddress', $mapping['name']);
$this->assertNull($mapping['entities'][0]['discriminatorColumn']);
$this->assertEquals(array('name'=>'id','column'=>'id'), $mapping['entities'][0]['fields'][0]);
$this->assertEquals(array('name'=>'name','column'=>'name'), $mapping['entities'][0]['fields'][1]);
$this->assertEquals(array('name'=>'status','column'=>'status'), $mapping['entities'][0]['fields'][2]);
$this->assertEquals(array('name'=>'address.zip','column'=>'zip'), $mapping['entities'][0]['fields'][3]);
$this->assertEquals(array('name'=>'address.city','column'=>'city'), $mapping['entities'][0]['fields'][4]);
$this->assertEquals(array('name'=>'address.country','column'=>'country'), $mapping['entities'][0]['fields'][5]);
$this->assertEquals(array('name'=>'address.id','column'=>'a_id'), $mapping['entities'][0]['fields'][6]);
$this->assertEquals($userMetadata->name, $mapping['entities'][0]['entityClass']);
$mapping = $userMetadata->getSqlResultSetMapping('mappingJoinedPhonenumber');
$this->assertEquals(array(),$mapping['columns']);
$this->assertEquals('mappingJoinedPhonenumber', $mapping['name']);
$this->assertNull($mapping['entities'][0]['discriminatorColumn']);
$this->assertEquals(array('name'=>'id','column'=>'id'), $mapping['entities'][0]['fields'][0]);
$this->assertEquals(array('name'=>'name','column'=>'name'), $mapping['entities'][0]['fields'][1]);
$this->assertEquals(array('name'=>'status','column'=>'status'), $mapping['entities'][0]['fields'][2]);
$this->assertEquals(array('name'=>'phonenumbers.phonenumber','column'=>'number'), $mapping['entities'][0]['fields'][3]);
$this->assertEquals($userMetadata->name, $mapping['entities'][0]['entityClass']);
$mapping = $userMetadata->getSqlResultSetMapping('mappingUserPhonenumberCount');
$this->assertEquals(array('name'=>'numphones'),$mapping['columns'][0]);
$this->assertEquals('mappingUserPhonenumberCount', $mapping['name']);
$this->assertNull($mapping['entities'][0]['discriminatorColumn']);
$this->assertEquals(array('name'=>'id','column'=>'id'), $mapping['entities'][0]['fields'][0]);
$this->assertEquals(array('name'=>'name','column'=>'name'), $mapping['entities'][0]['fields'][1]);
$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());
$mapping = $personMetadata->getSqlResultSetMapping('mappingFetchAll');
$this->assertEquals(array(),$mapping['columns']);
$this->assertEquals('mappingFetchAll', $mapping['name']);
$this->assertEquals('discriminator', $mapping['entities'][0]['discriminatorColumn']);
$this->assertEquals(array('name'=>'id','column'=>'id'), $mapping['entities'][0]['fields'][0]);
$this->assertEquals(array('name'=>'name','column'=>'name'), $mapping['entities'][0]['fields'][1]);
$this->assertEquals($personMetadata->name, $mapping['entities'][0]['entityClass']);
}
}
/**

View File

@ -510,6 +510,29 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals(1, count($cm->getNamedQueries()));
}
/**
* @group DDC-1663
*/
public function testRetrievalOfResultSetMappings()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
$this->assertEquals(0, count($cm->getSqlResultSetMappings()));
$cm->addSqlResultSetMapping(array(
'name' => 'find-all',
'entities' => array(
array(
'entityClass' => 'Doctrine\Tests\Models\CMS\CmsUser',
),
),
));
$this->assertEquals(1, count($cm->getSqlResultSetMappings()));
}
public function testExistanceOfNamedQuery()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
@ -525,6 +548,138 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
$this->assertFalse($cm->hasNamedQuery('userById'));
}
/**
* @group DDC-1663
*/
public function testRetrieveOfNamedNativeQuery()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
$cm->addNamedNativeQuery(array(
'name' => 'find-all',
'query' => 'SELECT * FROM cms_users',
'resultSetMapping' => 'result-mapping-name',
'resultClass' => 'Doctrine\Tests\Models\CMS\CmsUser',
));
$cm->addNamedNativeQuery(array(
'name' => 'find-by-id',
'query' => 'SELECT * FROM cms_users WHERE id = ?',
'resultClass' => '__CLASS__',
'resultSetMapping' => 'result-mapping-name',
));
$mapping = $cm->getNamedNativeQuery('find-all');
$this->assertEquals('SELECT * FROM cms_users', $mapping['query']);
$this->assertEquals('result-mapping-name', $mapping['resultSetMapping']);
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $mapping['resultClass']);
$mapping = $cm->getNamedNativeQuery('find-by-id');
$this->assertEquals('SELECT * FROM cms_users WHERE id = ?', $mapping['query']);
$this->assertEquals('result-mapping-name', $mapping['resultSetMapping']);
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $mapping['resultClass']);
}
/**
* @group DDC-1663
*/
public function testRetrieveOfSqlResultSetMapping()
{
$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'=> 'id'
),
array(
'name' => 'name',
'column'=> 'name'
)
)
),
array(
'entityClass' => 'Doctrine\Tests\Models\CMS\CmsEmail',
'fields' => array(
array(
'name' => 'id',
'column'=> 'id'
),
array(
'name' => 'email',
'column'=> 'email'
)
)
)
),
'columns' => array(
array(
'name' => 'scalarColumn'
)
)
));
$mapping = $cm->getSqlResultSetMapping('find-all');
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $mapping['entities'][0]['entityClass']);
$this->assertEquals(array('name'=>'id','column'=>'id'), $mapping['entities'][0]['fields'][0]);
$this->assertEquals(array('name'=>'name','column'=>'name'), $mapping['entities'][0]['fields'][1]);
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsEmail', $mapping['entities'][1]['entityClass']);
$this->assertEquals(array('name'=>'id','column'=>'id'), $mapping['entities'][1]['fields'][0]);
$this->assertEquals(array('name'=>'email','column'=>'email'), $mapping['entities'][1]['fields'][1]);
$this->assertEquals('scalarColumn', $mapping['columns'][0]['name']);
}
/**
* @group DDC-1663
*/
public function testExistanceOfSqlResultSetMapping()
{
$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' => 'Doctrine\Tests\Models\CMS\CmsUser',
),
),
));
$this->assertTrue($cm->hasSqlResultSetMapping('find-all'));
$this->assertFalse($cm->hasSqlResultSetMapping('find-by-id'));
}
/**
* @group DDC-1663
*/
public function testExistanceOfNamedNativeQuery()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
$cm->addNamedNativeQuery(array(
'name' => 'find-all',
'query' => 'SELECT * FROM cms_users',
'resultClass' => 'Doctrine\Tests\Models\CMS\CmsUser',
'resultSetMapping' => 'result-mapping-name'
));
$this->assertTrue($cm->hasNamedNativeQuery('find-all'));
$this->assertFalse($cm->hasNamedNativeQuery('find-by-id'));
}
public function testRetrieveOfNamedQuery()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
@ -539,13 +694,34 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?1', $cm->getNamedQuery('userById'));
}
public function testNamingCollisionNamedQueryShouldThrowException()
/**
* @group DDC-1663
*/
public function testRetrievalOfNamedNativeQueries()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
$this->assertEquals(0, count($cm->getNamedNativeQueries()));
$this->setExpectedException('Doctrine\ORM\Mapping\MappingException');
$cm->addNamedNativeQuery(array(
'name' => 'find-all',
'query' => 'SELECT * FROM cms_users',
'resultClass' => 'Doctrine\Tests\Models\CMS\CmsUser',
'resultSetMapping' => 'result-mapping-name'
));
$this->assertEquals(1, count($cm->getNamedNativeQueries()));
}
/**
* @expectedException \Doctrine\ORM\Mapping\MappingException
* @expectedExceptionMessage Query named "userById" in "Doctrine\Tests\Models\CMS\CmsUser" was already declared, but it must be declared only once
*/
public function testNamingCollisionNamedQueryShouldThrowException()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
$cm->addNamedQuery(array(
'name' => 'userById',
@ -558,6 +734,62 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
));
}
/**
* @group DDC-1663
*
* @expectedException \Doctrine\ORM\Mapping\MappingException
* @expectedExceptionMessage Query named "find-all" in "Doctrine\Tests\Models\CMS\CmsUser" was already declared, but it must be declared only once
*/
public function testNamingCollisionNamedNativeQueryShouldThrowException()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
$cm->addNamedNativeQuery(array(
'name' => 'find-all',
'query' => 'SELECT * FROM cms_users',
'resultClass' => 'Doctrine\Tests\Models\CMS\CmsUser',
'resultSetMapping' => 'result-mapping-name'
));
$cm->addNamedNativeQuery(array(
'name' => 'find-all',
'query' => 'SELECT * FROM cms_users',
'resultClass' => 'Doctrine\Tests\Models\CMS\CmsUser',
'resultSetMapping' => 'result-mapping-name'
));
}
/**
* @group DDC-1663
*
* @expectedException \Doctrine\ORM\Mapping\MappingException
* @expectedExceptionMessage Result set mapping named "find-all" in "Doctrine\Tests\Models\CMS\CmsUser" was already declared, but it must be declared only once
*/
public function testNamingCollisionSqlResultSetMappingShouldThrowException()
{
$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' => 'Doctrine\Tests\Models\CMS\CmsUser',
),
),
));
$cm->addSqlResultSetMapping(array(
'name' => 'find-all',
'entities' => array(
array(
'entityClass' => 'Doctrine\Tests\Models\CMS\CmsUser',
),
),
));
}
/**
* @group DDC-1068
*/
@ -596,6 +828,58 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
$cm->validateAssocations();
}
/**
* @group DDC-1663
*
* @expectedException \Doctrine\ORM\Mapping\MappingException
* @expectedExceptionMessage Query name on entity class 'Doctrine\Tests\Models\CMS\CmsUser' is not defined.
*/
public function testNameIsMandatoryForNamedQueryMappingException()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
$cm->addNamedQuery(array(
'query' => 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u',
));
}
/**
* @group DDC-1663
*
* @expectedException \Doctrine\ORM\Mapping\MappingException
* @expectedExceptionMessage Query name on entity class 'Doctrine\Tests\Models\CMS\CmsUser' is not defined.
*/
public function testNameIsMandatoryForNameNativeQueryMappingException()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
$cm->addNamedQuery(array(
'query' => 'SELECT * FROM cms_users',
'resultClass' => 'Doctrine\Tests\Models\CMS\CmsUser',
'resultSetMapping' => 'result-mapping-name'
));
}
/**
* @group DDC-1663
*
* @expectedException \Doctrine\ORM\Mapping\MappingException
* @expectedExceptionMessage Result set mapping named "find-all" in "Doctrine\Tests\Models\CMS\CmsUser requires a entity class name.
*/
public function testNameIsMandatoryForEntityNameSqlResultSetMappingException()
{
$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(
'fields' => array()
)
),
));
}
/**
* @expectedException \Doctrine\ORM\Mapping\MappingException
* @expectedExceptionMessage Discriminator column name on entity class 'Doctrine\Tests\Models\CMS\CmsUser' is not defined.

View File

@ -0,0 +1,69 @@
<?php
use Doctrine\ORM\Mapping\ClassMetadataInfo;
$metadata->setPrimaryTable(array(
'name' => 'company_person',
));
$metadata->addNamedNativeQuery(array (
'name' => 'find-all',
'query' => 'SELECT id, country, city FROM cms_addresses',
'resultSetMapping' => 'mapping-find-all',
));
$metadata->addNamedNativeQuery(array (
'name' => 'find-by-id',
'query' => 'SELECT * FROM cms_addresses WHERE id = ?',
'resultClass' => 'Doctrine\\Tests\\Models\\CMS\\CmsAddress',
));
$metadata->addNamedNativeQuery(array (
'name' => 'count',
'query' => 'SELECT COUNT(*) AS count FROM cms_addresses',
'resultSetMapping' => 'mapping-count',
));
$metadata->addSqlResultSetMapping(array (
'name' => 'mapping-find-all',
'columns' => array(),
'entities' => array ( array (
'fields' => array (
array (
'name' => 'id',
'column' => 'id',
),
array (
'name' => 'city',
'column' => 'city',
),
array (
'name' => 'country',
'column' => 'country',
),
),
'entityClass' => 'Doctrine\Tests\Models\CMS\CmsAddress',
),
),
));
$metadata->addSqlResultSetMapping(array (
'name' => 'mapping-without-fields',
'columns' => array(),
'entities' => array(array (
'entityClass' => 'Doctrine\\Tests\\Models\\CMS\\CmsAddress',
'fields' => array()
)
)
));
$metadata->addSqlResultSetMapping(array (
'name' => 'mapping-count',
'columns' =>array (
array (
'name' => 'count',
),
)
));

View File

@ -0,0 +1,186 @@
<?php
use Doctrine\ORM\Mapping\ClassMetadataInfo;
$metadata->setPrimaryTable(array(
'name' => 'cms_users',
));
$metadata->addNamedNativeQuery(array (
'name' => 'fetchIdAndUsernameWithResultClass',
'query' => 'SELECT id, username FROM cms_users WHERE username = ?',
'resultClass' => 'Doctrine\\Tests\\Models\\CMS\\CmsUser',
));
$metadata->addNamedNativeQuery(array (
'name' => 'fetchAllColumns',
'query' => 'SELECT * FROM cms_users WHERE username = ?',
'resultClass' => 'Doctrine\\Tests\\Models\\CMS\\CmsUser',
));
$metadata->addNamedNativeQuery(array (
'name' => 'fetchJoinedAddress',
'query' => 'SELECT u.id, u.name, u.status, a.id AS a_id, a.country, a.zip, a.city FROM cms_users u INNER JOIN cms_addresses a ON u.id = a.user_id WHERE u.username = ?',
'resultSetMapping' => 'mappingJoinedAddress',
));
$metadata->addNamedNativeQuery(array (
'name' => 'fetchJoinedPhonenumber',
'query' => 'SELECT id, name, status, phonenumber AS number FROM cms_users INNER JOIN cms_phonenumbers ON id = user_id WHERE username = ?',
'resultSetMapping' => 'mappingJoinedPhonenumber',
));
$metadata->addNamedNativeQuery(array (
'name' => 'fetchUserPhonenumberCount',
'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',
'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(),
'entities' => array(array (
'fields'=> array (
array (
'name' => 'id',
'column' => 'id',
),
array (
'name' => 'name',
'column' => 'name',
),
array (
'name' => 'status',
'column' => 'status',
),
array (
'name' => 'address.zip',
'column' => 'zip',
),
array (
'name' => 'address.city',
'column' => 'city',
),
array (
'name' => 'address.country',
'column' => 'country',
),
array (
'name' => 'address.id',
'column' => 'a_id',
),
),
'entityClass' => 'Doctrine\Tests\Models\CMS\CmsUser',
'discriminatorColumn' => null
),
),
));
$metadata->addSqlResultSetMapping(array (
'name' => 'mappingJoinedPhonenumber',
'columns' => array(),
'entities' => array(array(
'fields'=> array (
array (
'name' => 'id',
'column' => 'id',
),
array (
'name' => 'name',
'column' => 'name',
),
array (
'name' => 'status',
'column' => 'status',
),
array (
'name' => 'phonenumbers.phonenumber',
'column' => 'number',
),
),
'entityClass' => 'Doctrine\\Tests\\Models\\CMS\\CmsUser',
'discriminatorColumn' => null
),
),
));
$metadata->addSqlResultSetMapping(array (
'name' => 'mappingUserPhonenumberCount',
'columns' => array(),
'entities' => array (
array(
'fields' => array (
array (
'name' => 'id',
'column' => 'id',
),
array (
'name' => 'name',
'column' => 'name',
),
array (
'name' => 'status',
'column' => 'status',
)
),
'entityClass' => 'Doctrine\Tests\Models\CMS\CmsUser',
'discriminatorColumn' => null
)
),
'columns' => array (
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

@ -0,0 +1,39 @@
<?php
use Doctrine\ORM\Mapping\ClassMetadataInfo;
$metadata->setPrimaryTable(array(
'name' => 'company_person',
));
$metadata->addNamedNativeQuery(array (
'name' => 'fetchAllWithResultClass',
'query' => 'SELECT id, name, discr FROM company_persons ORDER BY name',
'resultClass' => 'Doctrine\\Tests\\Models\\Company\\CompanyPerson',
));
$metadata->addNamedNativeQuery(array (
'name' => 'fetchAllWithSqlResultSetMapping',
'query' => 'SELECT id, name, discr AS discriminator FROM company_persons ORDER BY name',
'resultSetMapping' => 'mappingFetchAll',
));
$metadata->addSqlResultSetMapping(array (
'name' => 'mappingFetchAll',
'columns' => array(),
'entities' => array ( array (
'fields' => array (
array (
'name' => 'id',
'column' => 'id',
),
array (
'name' => 'name',
'column' => 'name',
),
),
'entityClass' => 'Doctrine\Tests\Models\Company\CompanyPerson',
'discriminatorColumn' => 'discriminator',
),
),
));

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Doctrine\Tests\Models\CMS\CmsAddress" table="cms_users">
<named-native-queries>
<named-native-query name="find-all" result-set-mapping="mapping-find-all">
<query>SELECT id, country, city FROM cms_addresses</query>
</named-native-query>
<named-native-query name="find-by-id" result-class="CmsAddress">
<query>SELECT * FROM cms_addresses WHERE id = ?</query>
</named-native-query>
<named-native-query name="count" result-set-mapping="mapping-count">
<query>SELECT COUNT(*) AS count FROM cms_addresses</query>
</named-native-query>
</named-native-queries>
<sql-result-set-mappings>
<sql-result-set-mapping name="mapping-find-all">
<entity-result entity-class="CmsAddress">
<field-result name="id" column="id"/>
<field-result name="city" column="city"/>
<field-result name="country" column="country"/>
</entity-result>
</sql-result-set-mapping>
<sql-result-set-mapping name="mapping-without-fields">
<entity-result entity-class="CmsAddress"/>
</sql-result-set-mapping>
<sql-result-set-mapping name="mapping-count">
<column-result name="count"/>
</sql-result-set-mapping>
</sql-result-set-mappings>
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
</id>
<field name="country" column="country" type="string" length="50"/>
<field name="city" column="city" type="string" length="50"/>
<field name="zip" column="zip" type="string" length="50"/>
<one-to-one field="user" target-entity="CmsUser" inversed-by="address">
<join-column referenced-column-name="id" />
</one-to-one>
</entity>
</doctrine-mapping>

View File

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Doctrine\Tests\Models\CMS\CmsUser" table="cms_users">
<named-queries>
<named-query name="all" query="SELECT u FROM __CLASS__ u"/>
</named-queries>
<named-native-queries>
<named-native-query name="fetchIdAndUsernameWithResultClass" result-class="CmsUser">
<query>SELECT id, username FROM cms_users WHERE username = ?</query>
</named-native-query>
<named-native-query name="fetchAllColumns" result-class="CmsUser">
<query>SELECT * FROM cms_users WHERE username = ?</query>
</named-native-query>
<named-native-query name="fetchJoinedAddress" result-set-mapping="mappingJoinedAddress">
<query>SELECT u.id, u.name, u.status, a.id AS a_id, a.country, a.zip, a.city FROM cms_users u INNER JOIN cms_addresses a ON u.id = a.user_id WHERE u.username = ?</query>
</named-native-query>
<named-native-query name="fetchJoinedPhonenumber" result-set-mapping="mappingJoinedPhonenumber">
<query>SELECT id, name, status, phonenumber AS number FROM cms_users INNER JOIN cms_phonenumbers ON id = user_id WHERE username = ?</query>
</named-native-query>
<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>
<sql-result-set-mapping name="mappingJoinedAddress">
<entity-result entity-class="__CLASS__">
<field-result name="id"/>
<field-result name="name"/>
<field-result name="status"/>
<field-result name="address.zip"/>
<field-result name="address.city"/>
<field-result name="address.country"/>
<field-result name="address.id" column="a_id"/>
</entity-result>
</sql-result-set-mapping>
<sql-result-set-mapping name="mappingJoinedPhonenumber">
<entity-result entity-class="CmsUser">
<field-result name="id"/>
<field-result name="name"/>
<field-result name="status"/>
<field-result name="phonenumbers.phonenumber" column="number"/>
</entity-result>
</sql-result-set-mapping>
<sql-result-set-mapping name="mappingUserPhonenumberCount">
<entity-result entity-class="CmsUser">
<field-result name="id"/>
<field-result name="name"/>
<field-result name="status"/>
</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">
<generator strategy="AUTO"/>
</id>
<field name="status" column="status" type="string" length="50" unique="true"/>
<field name="username" column="username" type="string" length="255" unique="true"/>
<field name="name" column="name" type="string" length="255"/>
<one-to-many field="phonenumbers" target-entity="CmsPhonenumber" mapped-by="user" orphan-removal="true">
<cascade>
<cascade-persist/>
<cascade-merge/>
</cascade>
</one-to-many>
<one-to-many field="articles" target-entity="CmsArticle" mapped-by="user">
<cascade>
<cascade-detach/>
</cascade>
</one-to-many>
<one-to-one field="address" target-entity="CmsAddress" inversed-by="user" orphan-removal="true">
<cascade>
<cascade-persist/>
</cascade>
<join-column name="address_id" referenced-column-name="id" />
</one-to-one>
<one-to-one field="email" target-entity="CmsEmail" inversed-by="user" orphan-removal="true">
<cascade>
<cascade-persist/>
</cascade>
<join-column referenced-column-name="id" nullable="true" />
</one-to-one>
<many-to-many field="groups" target-entity="CmsGroup">
<cascade>
<cascade-persist/>
<cascade-detach/>
<cascade-merge/>
</cascade>
<join-table name="cms_users_groups">
<join-columns>
<join-column name="user_id" referenced-column-name="id"/>
</join-columns>
<inverse-join-columns>
<join-column name="group_id" referenced-column-name="id"/>
</inverse-join-columns>
</join-table>
</many-to-many>
</entity>
</doctrine-mapping>

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Doctrine\Tests\Models\Company\CompanyPerson" table="company_persons" inheritance-type="JOINED">
<named-native-queries>
<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-query name="fetchAllWithSqlResultSetMapping" result-set-mapping="mappingFetchAll">
<query>SELECT id, name, discr AS discriminator FROM company_persons ORDER BY name</query>
</named-native-query>
</named-native-queries>
<sql-result-set-mappings>
<sql-result-set-mapping name="mappingFetchAll">
<entity-result entity-class="__CLASS__" discriminator-column="discriminator">
<field-result name="id"/>
<field-result name="name"/>
</entity-result>
</sql-result-set-mapping>
</sql-result-set-mappings>
<discriminator-map >
<discriminator-mapping value="person" class="CompanyPerson" />
<discriminator-mapping value="manager" class="CompanyManager" />
<discriminator-mapping value="employee" class="CompanyEmployee" />
</discriminator-map>
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
</id>
<field name="name" column="name"/>
<one-to-one field="spouse" target-entity="CompanyPerson">
<join-column name="spouse_id" referenced-column-name="id"/>
</one-to-one>
<many-to-many field="friends" target-entity="CompanyPerson">
<join-table name="company_persons_friends">
<join-columns>
<join-column name="person_id" referenced-column-name="id"/>
</join-columns>
<inverse-join-columns>
<join-column name="friend_id" referenced-column-name="id"/>
</inverse-join-columns>
</join-table>
</many-to-many>
</entity>
</doctrine-mapping>

View File

@ -0,0 +1,62 @@
Doctrine\Tests\Models\CMS\CmsAddress:
type: entity
table: cms_address
namedNativeQueries:
find-all:
resultSetMapping: mapping-find-all
query: SELECT id, country, city FROM cms_addresses
find-by-id:
name: find-by-id
resultClass: CmsAddress
query: SELECT * FROM cms_addresses WHERE id = ?
count:
name: count
resultSetMapping: mapping-count
query: SELECT COUNT(*) AS count FROM cms_addresses
sqlResultSetMappings:
mapping-find-all:
entityResult:
address:
entityClass: CmsAddress
fieldResult:
0:
name: id
column: id
1:
name: city
column: city
2:
name: country
column: country
mapping-without-fields:
name: mapping-without-fields
entityResult:
address:
entityClass: CmsAddress
mapping-count:
name: mapping-count
columnResult:
count:
name: count
id:
id:
type: integer
generator:
strategy: AUTO
fields:
country:
type: string
length: 50
city:
type: string
length: 50
zip:
type: string
length: 50
oneToOne:
address:
targetEntity: CmsUser
inversedBy: address
joinColumn:
referencedColumnName: id

View File

@ -0,0 +1,158 @@
Doctrine\Tests\Models\CMS\CmsUser:
type: entity
table: cms_users
namedQueries:
all: SELECT u FROM __CLASS__ u
namedNativeQueries:
fetchIdAndUsernameWithResultClass:
resultClass: CmsUser
query: SELECT id, username FROM cms_users WHERE username = ?
fetchAllColumns:
name: fetchAllColumns
resultClass: CmsUser
query: SELECT * FROM cms_users WHERE username = ?
fetchJoinedAddress:
name: fetchJoinedAddress
resultSetMapping: mappingJoinedAddress
query: SELECT u.id, u.name, u.status, a.id AS a_id, a.country, a.zip, a.city FROM cms_users u INNER JOIN cms_addresses a ON u.id = a.user_id WHERE u.username = ?
fetchJoinedPhonenumber:
name: fetchJoinedPhonenumber
resultSetMapping: mappingJoinedPhonenumber
query: SELECT id, name, status, phonenumber AS number FROM cms_users INNER JOIN cms_phonenumbers ON id = user_id WHERE username = ?
fetchUserPhonenumberCount:
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:
entityResult:
0:
entityClass: __CLASS__
fieldResult:
0:
name: id
1:
name: name
2:
name: status
3:
name: address.zip
4:
name: address.city
5:
name: address.country
6:
name: address.id
column: a_id
mappingJoinedPhonenumber:
name: mappingJoinedPhonenumber
entityResult:
user:
entityClass: CmsUser
fieldResult:
0:
name: id
1:
name: name
2:
name: status
3:
name: phonenumbers.phonenumber
column: number
mappingUserPhonenumberCount:
name: mappingUserPhonenumberCount
columnResult:
0:
name: numphones
entityResult:
user_0:
entityClass: CmsUser
fieldResult:
0:
name: id
1:
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
generator:
strategy: AUTO
fields:
name:
type: string
length: 255
username:
type: string
length: 255
unique: true
status:
type: string
length: 50
unique: true
oneToOne:
address:
targetEntity: CmsAddress
orphanRemoval: true
inversedBy: user
joinColumn:
name: address_id
referencedColumnName: id
cascade: [ persist ]
oneToOne:
email:
targetEntity: CmsEmail
orphanRemoval: true
inversedBy: user
joinColumn:
nullable: true
referencedColumnName: id
cascade: [ persist ]
manyToMany:
groups:
targetEntity: CmsGroup
joinTable:
name: cms_users_groups
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
group_id:
referencedColumnName: id
cascade: [ persist , detach, merge]

View File

@ -0,0 +1,75 @@
Doctrine\Tests\Models\Company\CompanyPerson:
type: entity
table: company_persons
inheritanceType: JOINED
discriminatorMap:
person: CompanyPerson
manager: CompanyManager
employee: CompanyEmployee
namedNativeQueries:
fetchAllWithResultClass:
resultClass: __CLASS__
query: SELECT id, name, discr FROM company_persons ORDER BY name
fetchAllWithSqlResultSetMapping:
name: fetchAllWithSqlResultSetMapping
resultSetMapping: mappingFetchAll
query: SELECT id, name, discr AS discriminator FROM company_persons ORDER BY name
sqlResultSetMappings:
mappingFetchAll:
entityResult:
0:
entityClass: __CLASS__
discriminatorColumn: discriminator
fieldResult:
0:
name: id
1:
name: name
id:
id:
type: integer
generator:
strategy: AUTO
fields:
name:
type: string
length: 255
username:
type: string
length: 255
unique: true
status:
type: string
length: 50
unique: true
oneToOne:
address:
targetEntity: CmsAddress
orphanRemoval: true
inversedBy: user
joinColumn:
name: address_id
referencedColumnName: id
cascade: [ persist ]
oneToOne:
email:
targetEntity: CmsEmail
orphanRemoval: true
inversedBy: user
joinColumn:
nullable: true
referencedColumnName: id
cascade: [ persist ]
manyToMany:
groups:
targetEntity: CmsGroup
joinTable:
name: cms_users_groups
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
group_id:
referencedColumnName: id
cascade: [ persist , detach, merge]

View File

@ -147,6 +147,7 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
$conn->executeUpdate('DELETE FROM cms_comments');
$conn->executeUpdate('DELETE FROM cms_articles');
$conn->executeUpdate('DELETE FROM cms_users');
$conn->executeUpdate('DELETE FROM cms_emails');
}
if (isset($this->_usedModelSets['ecommerce'])) {