Merge branch 'master' into DDC-1452
This commit is contained in:
commit
98033cc878
3
.gitignore
vendored
3
.gitignore
vendored
@ -7,3 +7,6 @@ download/
|
||||
lib/api/
|
||||
lib/Doctrine/Common
|
||||
lib/Doctrine/DBAL
|
||||
/.settings/
|
||||
.buildpath
|
||||
.project
|
||||
|
19
.travis.yml
Normal file
19
.travis.yml
Normal file
@ -0,0 +1,19 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
env:
|
||||
- DB=mysql
|
||||
- DB=pgsql
|
||||
- DB=sqlite
|
||||
|
||||
before_script:
|
||||
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'DROP DATABASE IF EXISTS doctrine_tests;' -U postgres; fi"
|
||||
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'DROP DATABASE IF EXISTS doctrine_tests_tmp;' -U postgres; fi"
|
||||
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'create database doctrine_tests;' -U postgres; fi"
|
||||
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'create database doctrine_tests_tmp;' -U postgres; fi"
|
||||
- sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS doctrine_tests_tmp;create database IF NOT EXISTS doctrine_tests;'; fi"
|
||||
- git submodule update --init
|
||||
|
||||
script: phpunit --configuration tests/travis/$DB.travis.xml
|
@ -1,14 +1,18 @@
|
||||
# Doctrine 2 ORM
|
||||
|
||||
Master: [](http://travis-ci.org/doctrine/doctrine2)
|
||||
2.1.x: [](http://travis-ci.org/doctrine/doctrine2)
|
||||
|
||||
Doctrine 2 is an object-relational mapper (ORM) for PHP 5.3.2+ that provides transparent persistence
|
||||
for PHP objects. It sits on top of a powerful database abstraction layer (DBAL). One of its key features
|
||||
is the option to write database queries in a proprietary object oriented SQL dialect called Doctrine Query Language (DQL),
|
||||
inspired by Hibernates HQL. This provides developers with a powerful alternative to SQL that maintains flexibility
|
||||
without requiring unnecessary code duplication.
|
||||
|
||||
More resources:
|
||||
## More resources:
|
||||
|
||||
* [Website](http://www.doctrine-project.org)
|
||||
* [Documentation](http://www.doctrine-project.org/projects/orm/2.0/docs/reference/introduction/en)
|
||||
* [Issue Tracker](http://www.doctrine-project.org/jira/browse/DDC)
|
||||
* [Downloads](http://github.com/doctrine/doctrine2/downloads)
|
||||
* [Downloads](http://github.com/doctrine/doctrine2/downloads)
|
||||
|
||||
|
@ -16,5 +16,8 @@
|
||||
"ext-pdo": "*",
|
||||
"doctrine/common": "master-dev",
|
||||
"doctrine/dbal": "master-dev"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "Doctrine\\ORM": "lib/" }
|
||||
}
|
||||
}
|
||||
|
@ -545,7 +545,7 @@ abstract class AbstractQuery
|
||||
*
|
||||
* @param array $params The query parameters.
|
||||
* @param integer $hydrationMode The hydration mode to use.
|
||||
* @return IterableResult
|
||||
* @return \Doctrine\ORM\Internal\Hydration\IterableResult
|
||||
*/
|
||||
public function iterate(array $params = array(), $hydrationMode = null)
|
||||
{
|
||||
|
@ -225,6 +225,14 @@ class EntityRepository implements ObjectRepository
|
||||
return $this->_entityName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getClassName()
|
||||
{
|
||||
return $this->getEntityName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EntityManager
|
||||
*/
|
||||
@ -240,4 +248,4 @@ class EntityRepository implements ObjectRepository
|
||||
{
|
||||
return $this->_class;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
53
lib/Doctrine/ORM/Event/PreFlushEventArgs.php
Normal file
53
lib/Doctrine/ORM/Event/PreFlushEventArgs.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* 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\Event;
|
||||
|
||||
/**
|
||||
* Provides event arguments for the preFlush event.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.com
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
* @author Roman Borschel <roman@code-factory.de>
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class PreFlushEventArgs extends \Doctrine\Common\EventArgs
|
||||
{
|
||||
/**
|
||||
* @var EntityManager
|
||||
*/
|
||||
private $_em;
|
||||
|
||||
public function __construct($em)
|
||||
{
|
||||
$this->_em = $em;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EntityManager
|
||||
*/
|
||||
public function getEntityManager()
|
||||
{
|
||||
return $this->_em;
|
||||
}
|
||||
}
|
@ -109,6 +109,13 @@ final class Events
|
||||
*/
|
||||
const loadClassMetadata = 'loadClassMetadata';
|
||||
|
||||
/**
|
||||
* The preFlush event occurs when the EntityManager#flush() operation is invoked,
|
||||
* but before any changes to managed entites have been calculated. This event is
|
||||
* always raised right after EntityManager#flush() call.
|
||||
*/
|
||||
const preFlush = 'preFlush';
|
||||
|
||||
/**
|
||||
* The onFlush event occurs when the EntityManager#flush() operation is invoked,
|
||||
* after any changes to managed entities have been determined but before any
|
||||
|
@ -20,6 +20,7 @@
|
||||
namespace Doctrine\ORM\Id;
|
||||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\ORMException;
|
||||
|
||||
/**
|
||||
@ -42,46 +43,29 @@ class AssignedGenerator extends AbstractIdGenerator
|
||||
*/
|
||||
public function generate(EntityManager $em, $entity)
|
||||
{
|
||||
$class = $em->getClassMetadata(get_class($entity));
|
||||
$class = $em->getClassMetadata(get_class($entity));
|
||||
$idFields = $class->getIdentifierFieldNames();
|
||||
$identifier = array();
|
||||
if ($class->isIdentifierComposite) {
|
||||
$idFields = $class->getIdentifierFieldNames();
|
||||
foreach ($idFields as $idField) {
|
||||
$value = $class->reflFields[$idField]->getValue($entity);
|
||||
if (isset($value)) {
|
||||
if (isset($class->associationMappings[$idField])) {
|
||||
if (!$em->getUnitOfWork()->isInIdentityMap($value)) {
|
||||
throw ORMException::entityMissingForeignAssignedId($entity, $value);
|
||||
}
|
||||
|
||||
// NOTE: Single Columns as associated identifiers only allowed - this constraint it is enforced.
|
||||
$identifier[$idField] = current($em->getUnitOfWork()->getEntityIdentifier($value));
|
||||
} else {
|
||||
$identifier[$idField] = $value;
|
||||
}
|
||||
} else {
|
||||
throw ORMException::entityMissingAssignedIdForField($entity, $idField);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$idField = $class->identifier[0];
|
||||
|
||||
foreach ($idFields as $idField) {
|
||||
$value = $class->reflFields[$idField]->getValue($entity);
|
||||
if (isset($value)) {
|
||||
if (isset($class->associationMappings[$idField])) {
|
||||
if (!$em->getUnitOfWork()->isInIdentityMap($value)) {
|
||||
throw ORMException::entityMissingForeignAssignedId($entity, $value);
|
||||
}
|
||||
|
||||
// NOTE: Single Columns as associated identifiers only allowed - this constraint it is enforced.
|
||||
$identifier[$idField] = current($em->getUnitOfWork()->getEntityIdentifier($value));
|
||||
} else {
|
||||
$identifier[$idField] = $value;
|
||||
}
|
||||
} else {
|
||||
|
||||
if ( ! isset($value)) {
|
||||
throw ORMException::entityMissingAssignedIdForField($entity, $idField);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($class->associationMappings[$idField])) {
|
||||
if ( ! $em->getUnitOfWork()->isInIdentityMap($value)) {
|
||||
throw ORMException::entityMissingForeignAssignedId($entity, $value);
|
||||
}
|
||||
|
||||
// NOTE: Single Columns as associated identifiers only allowed - this constraint it is enforced.
|
||||
$value = current($em->getUnitOfWork()->getEntityIdentifier($value));
|
||||
}
|
||||
|
||||
$identifier[$idField] = $value;
|
||||
}
|
||||
|
||||
return $identifier;
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ class IdentityGenerator extends AbstractIdGenerator
|
||||
*/
|
||||
public function generate(EntityManager $em, $entity)
|
||||
{
|
||||
return $em->getConnection()->lastInsertId($this->_seqName);
|
||||
return (int)$em->getConnection()->lastInsertId($this->_seqName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -46,7 +46,7 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
|
||||
$this->_sequenceName = $sequenceName;
|
||||
$this->_allocationSize = $allocationSize;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates an ID for the given entity.
|
||||
*
|
||||
@ -59,10 +59,12 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
|
||||
if ($this->_maxValue === null || $this->_nextValue == $this->_maxValue) {
|
||||
// Allocate new values
|
||||
$conn = $em->getConnection();
|
||||
$sql = $conn->getDatabasePlatform()->getSequenceNextValSQL($this->_sequenceName);
|
||||
$this->_nextValue = $conn->fetchColumn($sql);
|
||||
$this->_maxValue = $this->_nextValue + $this->_allocationSize;
|
||||
$sql = $conn->getDatabasePlatform()->getSequenceNextValSQL($this->_sequenceName);
|
||||
|
||||
$this->_nextValue = (int)$conn->fetchColumn($sql);
|
||||
$this->_maxValue = $this->_nextValue + $this->_allocationSize;
|
||||
}
|
||||
|
||||
return $this->_nextValue++;
|
||||
}
|
||||
|
||||
@ -90,13 +92,14 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
|
||||
{
|
||||
return serialize(array(
|
||||
'allocationSize' => $this->_allocationSize,
|
||||
'sequenceName' => $this->_sequenceName
|
||||
'sequenceName' => $this->_sequenceName
|
||||
));
|
||||
}
|
||||
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
$array = unserialize($serialized);
|
||||
|
||||
$this->_sequenceName = $array['sequenceName'];
|
||||
$this->_allocationSize = $array['allocationSize'];
|
||||
}
|
||||
|
@ -50,11 +50,12 @@ class TableGenerator extends AbstractIdGenerator
|
||||
if ($this->_maxValue === null || $this->_nextValue == $this->_maxValue) {
|
||||
// Allocate new values
|
||||
$conn = $em->getConnection();
|
||||
if ($conn->getTransactionNestingLevel() == 0) {
|
||||
|
||||
|
||||
if ($conn->getTransactionNestingLevel() === 0) {
|
||||
// use select for update
|
||||
$sql = $conn->getDatabasePlatform()->getTableHiLoCurrentValSql($this->_tableName, $this->_sequenceName);
|
||||
$sql = $conn->getDatabasePlatform()->getTableHiLoCurrentValSql($this->_tableName, $this->_sequenceName);
|
||||
$currentLevel = $conn->fetchColumn($sql);
|
||||
|
||||
if ($currentLevel != null) {
|
||||
$this->_nextValue = $currentLevel;
|
||||
$this->_maxValue = $this->_nextValue + $this->_allocationSize;
|
||||
@ -74,6 +75,7 @@ class TableGenerator extends AbstractIdGenerator
|
||||
// or do we want to work with table locks exclusively?
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_nextValue++;
|
||||
}
|
||||
}
|
@ -22,15 +22,17 @@ namespace Doctrine\ORM\Internal\Hydration;
|
||||
use PDO,
|
||||
Doctrine\DBAL\Connection,
|
||||
Doctrine\DBAL\Types\Type,
|
||||
Doctrine\ORM\EntityManager;
|
||||
Doctrine\ORM\EntityManager,
|
||||
Doctrine\ORM\Mapping\ClassMetadata;
|
||||
|
||||
/**
|
||||
* Base class for all hydrators. A hydrator is a class that provides some form
|
||||
* of transformation of an SQL result set into another structure.
|
||||
*
|
||||
* @since 2.0
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @author Guilherme Blanco <guilhermeblanoc@hotmail.com>
|
||||
*/
|
||||
abstract class AbstractHydrator
|
||||
{
|
||||
@ -62,9 +64,9 @@ abstract class AbstractHydrator
|
||||
*/
|
||||
public function __construct(EntityManager $em)
|
||||
{
|
||||
$this->_em = $em;
|
||||
$this->_em = $em;
|
||||
$this->_platform = $em->getConnection()->getDatabasePlatform();
|
||||
$this->_uow = $em->getUnitOfWork();
|
||||
$this->_uow = $em->getUnitOfWork();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,14 +74,17 @@ abstract class AbstractHydrator
|
||||
*
|
||||
* @param object $stmt
|
||||
* @param object $resultSetMapping
|
||||
*
|
||||
* @return IterableResult
|
||||
*/
|
||||
public function iterate($stmt, $resultSetMapping, array $hints = array())
|
||||
{
|
||||
$this->_stmt = $stmt;
|
||||
$this->_rsm = $resultSetMapping;
|
||||
$this->_stmt = $stmt;
|
||||
$this->_rsm = $resultSetMapping;
|
||||
$this->_hints = $hints;
|
||||
$this->_prepare();
|
||||
|
||||
$this->prepare();
|
||||
|
||||
return new IterableResult($this);
|
||||
}
|
||||
|
||||
@ -92,12 +97,16 @@ abstract class AbstractHydrator
|
||||
*/
|
||||
public function hydrateAll($stmt, $resultSetMapping, array $hints = array())
|
||||
{
|
||||
$this->_stmt = $stmt;
|
||||
$this->_rsm = $resultSetMapping;
|
||||
$this->_stmt = $stmt;
|
||||
$this->_rsm = $resultSetMapping;
|
||||
$this->_hints = $hints;
|
||||
$this->_prepare();
|
||||
$result = $this->_hydrateAll();
|
||||
$this->_cleanup();
|
||||
|
||||
$this->prepare();
|
||||
|
||||
$result = $this->hydrateAllData();
|
||||
|
||||
$this->cleanup();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@ -110,12 +119,17 @@ abstract class AbstractHydrator
|
||||
public function hydrateRow()
|
||||
{
|
||||
$row = $this->_stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ( ! $row) {
|
||||
$this->_cleanup();
|
||||
$this->cleanup();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = array();
|
||||
$this->_hydrateRow($row, $this->_cache, $result);
|
||||
|
||||
$this->hydrateRowData($row, $this->_cache, $result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@ -123,16 +137,17 @@ abstract class AbstractHydrator
|
||||
* Excutes one-time preparation tasks, once each time hydration is started
|
||||
* through {@link hydrateAll} or {@link iterate()}.
|
||||
*/
|
||||
protected function _prepare()
|
||||
protected function prepare()
|
||||
{}
|
||||
|
||||
/**
|
||||
* Excutes one-time cleanup tasks at the end of a hydration that was initiated
|
||||
* through {@link hydrateAll} or {@link iterate()}.
|
||||
*/
|
||||
protected function _cleanup()
|
||||
protected function cleanup()
|
||||
{
|
||||
$this->_rsm = null;
|
||||
|
||||
$this->_stmt->closeCursor();
|
||||
$this->_stmt = null;
|
||||
}
|
||||
@ -146,23 +161,24 @@ abstract class AbstractHydrator
|
||||
* @param array $cache The cache to use.
|
||||
* @param mixed $result The result to fill.
|
||||
*/
|
||||
protected function _hydrateRow(array $data, array &$cache, array &$result)
|
||||
protected function hydrateRowData(array $data, array &$cache, array &$result)
|
||||
{
|
||||
throw new HydrationException("_hydrateRow() not implemented by this hydrator.");
|
||||
throw new HydrationException("hydrateRowData() not implemented by this hydrator.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrates all rows from the current statement instance at once.
|
||||
*/
|
||||
abstract protected function _hydrateAll();
|
||||
abstract protected function hydrateAllData();
|
||||
|
||||
/**
|
||||
* Processes a row of the result set.
|
||||
*
|
||||
* Used for identity-based hydration (HYDRATE_OBJECT and HYDRATE_ARRAY).
|
||||
* Puts the elements of a result row into a new array, grouped by the class
|
||||
* Puts the elements of a result row into a new array, grouped by the dql alias
|
||||
* they belong to. The column names in the result set are mapped to their
|
||||
* field names during this procedure as well as any necessary conversions on
|
||||
* the values applied.
|
||||
* the values applied. Scalar values are kept in a specfic key 'scalars'.
|
||||
*
|
||||
* @param array $data SQL Result Row
|
||||
* @param array &$cache Cache for column to field result information
|
||||
@ -172,40 +188,51 @@ abstract class AbstractHydrator
|
||||
* @return array An array with all the fields (name => value) of the data row,
|
||||
* grouped by their component alias.
|
||||
*/
|
||||
protected function _gatherRowData(array $data, array &$cache, array &$id, array &$nonemptyComponents)
|
||||
protected function gatherRowData(array $data, array &$cache, array &$id, array &$nonemptyComponents)
|
||||
{
|
||||
$rowData = array();
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
// Parse each column name only once. Cache the results.
|
||||
if ( ! isset($cache[$key])) {
|
||||
if (isset($this->_rsm->scalarMappings[$key])) {
|
||||
$cache[$key]['fieldName'] = $this->_rsm->scalarMappings[$key];
|
||||
$cache[$key]['isScalar'] = true;
|
||||
} else if (isset($this->_rsm->fieldMappings[$key])) {
|
||||
$fieldName = $this->_rsm->fieldMappings[$key];
|
||||
$classMetadata = $this->_em->getClassMetadata($this->_rsm->declaringClasses[$key]);
|
||||
$cache[$key]['fieldName'] = $fieldName;
|
||||
$cache[$key]['type'] = Type::getType($classMetadata->fieldMappings[$fieldName]['type']);
|
||||
$cache[$key]['isIdentifier'] = $classMetadata->isIdentifier($fieldName);
|
||||
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
|
||||
} else if (!isset($this->_rsm->metaMappings[$key])) {
|
||||
// this column is a left over, maybe from a LIMIT query hack for example in Oracle or DB2
|
||||
// maybe from an additional column that has not been defined in a NativeQuery ResultSetMapping.
|
||||
continue;
|
||||
} else {
|
||||
// Meta column (has meaning in relational schema only, i.e. foreign keys or discriminator columns).
|
||||
$fieldName = $this->_rsm->metaMappings[$key];
|
||||
$cache[$key]['isMetaColumn'] = true;
|
||||
$cache[$key]['fieldName'] = $fieldName;
|
||||
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
|
||||
$classMetadata = $this->_em->getClassMetadata($this->_rsm->aliasMap[$cache[$key]['dqlAlias']]);
|
||||
$cache[$key]['isIdentifier'] = isset($this->_rsm->isIdentifierColumn[$cache[$key]['dqlAlias']][$key]);
|
||||
switch (true) {
|
||||
// NOTE: Most of the times it's a field mapping, so keep it first!!!
|
||||
case (isset($this->_rsm->fieldMappings[$key])):
|
||||
$fieldName = $this->_rsm->fieldMappings[$key];
|
||||
$classMetadata = $this->_em->getClassMetadata($this->_rsm->declaringClasses[$key]);
|
||||
|
||||
$cache[$key]['fieldName'] = $fieldName;
|
||||
$cache[$key]['type'] = Type::getType($classMetadata->fieldMappings[$fieldName]['type']);
|
||||
$cache[$key]['isIdentifier'] = $classMetadata->isIdentifier($fieldName);
|
||||
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
|
||||
break;
|
||||
|
||||
case (isset($this->_rsm->scalarMappings[$key])):
|
||||
$cache[$key]['fieldName'] = $this->_rsm->scalarMappings[$key];
|
||||
$cache[$key]['isScalar'] = true;
|
||||
break;
|
||||
|
||||
case (isset($this->_rsm->metaMappings[$key])):
|
||||
// Meta column (has meaning in relational schema only, i.e. foreign keys or discriminator columns).
|
||||
$fieldName = $this->_rsm->metaMappings[$key];
|
||||
$classMetadata = $this->_em->getClassMetadata($this->_rsm->aliasMap[$this->_rsm->columnOwnerMap[$key]]);
|
||||
|
||||
$cache[$key]['isMetaColumn'] = true;
|
||||
$cache[$key]['fieldName'] = $fieldName;
|
||||
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
|
||||
$cache[$key]['isIdentifier'] = isset($this->_rsm->isIdentifierColumn[$cache[$key]['dqlAlias']][$key]);
|
||||
break;
|
||||
|
||||
default:
|
||||
// this column is a left over, maybe from a LIMIT query hack for example in Oracle or DB2
|
||||
// maybe from an additional column that has not been defined in a NativeQuery ResultSetMapping.
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isset($cache[$key]['isScalar'])) {
|
||||
$rowData['scalars'][$cache[$key]['fieldName']] = $value;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -216,13 +243,14 @@ abstract class AbstractHydrator
|
||||
}
|
||||
|
||||
if (isset($cache[$key]['isMetaColumn'])) {
|
||||
if (!isset($rowData[$dqlAlias][$cache[$key]['fieldName']]) || $value !== null) {
|
||||
if ( ! isset($rowData[$dqlAlias][$cache[$key]['fieldName']]) || $value !== null) {
|
||||
$rowData[$dqlAlias][$cache[$key]['fieldName']] = $value;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// in an inheritance hierachy the same field could be defined several times.
|
||||
|
||||
// in an inheritance hierarchy the same field could be defined several times.
|
||||
// We overwrite this value so long we dont have a non-null value, that value we keep.
|
||||
// Per definition it cannot be that a field is defined several times and has several values.
|
||||
if (isset($rowData[$dqlAlias][$cache[$key]['fieldName']]) && $value === null) {
|
||||
@ -241,6 +269,7 @@ abstract class AbstractHydrator
|
||||
|
||||
/**
|
||||
* Processes a row of the result set.
|
||||
*
|
||||
* Used for HYDRATE_SCALAR. This is a variant of _gatherRowData() that
|
||||
* simply converts column names to field names and properly converts the
|
||||
* values according to their types. The resulting row has the same number
|
||||
@ -248,52 +277,77 @@ abstract class AbstractHydrator
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $cache
|
||||
*
|
||||
* @return array The processed row.
|
||||
*/
|
||||
protected function _gatherScalarRowData(&$data, &$cache)
|
||||
protected function gatherScalarRowData(&$data, &$cache)
|
||||
{
|
||||
$rowData = array();
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
// Parse each column name only once. Cache the results.
|
||||
if ( ! isset($cache[$key])) {
|
||||
if (isset($this->_rsm->scalarMappings[$key])) {
|
||||
$cache[$key]['fieldName'] = $this->_rsm->scalarMappings[$key];
|
||||
$cache[$key]['isScalar'] = true;
|
||||
} else if (isset($this->_rsm->fieldMappings[$key])) {
|
||||
$fieldName = $this->_rsm->fieldMappings[$key];
|
||||
$classMetadata = $this->_em->getClassMetadata($this->_rsm->declaringClasses[$key]);
|
||||
$cache[$key]['fieldName'] = $fieldName;
|
||||
$cache[$key]['type'] = Type::getType($classMetadata->fieldMappings[$fieldName]['type']);
|
||||
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
|
||||
} else if (!isset($this->_rsm->metaMappings[$key])) {
|
||||
// this column is a left over, maybe from a LIMIT query hack for example in Oracle or DB2
|
||||
// maybe from an additional column that has not been defined in a NativeQuery ResultSetMapping.
|
||||
continue;
|
||||
} else {
|
||||
// Meta column (has meaning in relational schema only, i.e. foreign keys or discriminator columns).
|
||||
$cache[$key]['isMetaColumn'] = true;
|
||||
$cache[$key]['fieldName'] = $this->_rsm->metaMappings[$key];
|
||||
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
|
||||
switch (true) {
|
||||
// NOTE: During scalar hydration, most of the times it's a scalar mapping, keep it first!!!
|
||||
case (isset($this->_rsm->scalarMappings[$key])):
|
||||
$cache[$key]['fieldName'] = $this->_rsm->scalarMappings[$key];
|
||||
$cache[$key]['isScalar'] = true;
|
||||
break;
|
||||
|
||||
case (isset($this->_rsm->fieldMappings[$key])):
|
||||
$fieldName = $this->_rsm->fieldMappings[$key];
|
||||
$classMetadata = $this->_em->getClassMetadata($this->_rsm->declaringClasses[$key]);
|
||||
|
||||
$cache[$key]['fieldName'] = $fieldName;
|
||||
$cache[$key]['type'] = Type::getType($classMetadata->fieldMappings[$fieldName]['type']);
|
||||
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
|
||||
break;
|
||||
|
||||
case (isset($this->_rsm->metaMappings[$key])):
|
||||
// Meta column (has meaning in relational schema only, i.e. foreign keys or discriminator columns).
|
||||
$cache[$key]['isMetaColumn'] = true;
|
||||
$cache[$key]['fieldName'] = $this->_rsm->metaMappings[$key];
|
||||
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
|
||||
break;
|
||||
|
||||
default:
|
||||
// this column is a left over, maybe from a LIMIT query hack for example in Oracle or DB2
|
||||
// maybe from an additional column that has not been defined in a NativeQuery ResultSetMapping.
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$fieldName = $cache[$key]['fieldName'];
|
||||
|
||||
if (isset($cache[$key]['isScalar'])) {
|
||||
$rowData[$fieldName] = $value;
|
||||
} else if (isset($cache[$key]['isMetaColumn'])) {
|
||||
$rowData[$cache[$key]['dqlAlias'] . '_' . $fieldName] = $value;
|
||||
} else {
|
||||
$rowData[$cache[$key]['dqlAlias'] . '_' . $fieldName] = $cache[$key]['type']
|
||||
->convertToPHPValue($value, $this->_platform);
|
||||
switch (true) {
|
||||
case (isset($cache[$key]['isScalar'])):
|
||||
$rowData[$fieldName] = $value;
|
||||
break;
|
||||
|
||||
case (isset($cache[$key]['isMetaColumn'])):
|
||||
$rowData[$cache[$key]['dqlAlias'] . '_' . $fieldName] = $value;
|
||||
break;
|
||||
|
||||
default:
|
||||
$value = $cache[$key]['type']->convertToPHPValue($value, $this->_platform);
|
||||
|
||||
$rowData[$cache[$key]['dqlAlias'] . '_' . $fieldName] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $rowData;
|
||||
}
|
||||
|
||||
protected function registerManaged($class, $entity, $data)
|
||||
|
||||
/**
|
||||
* Register entity as managed in UnitOfWork.
|
||||
*
|
||||
* @param Doctrine\ORM\Mapping\ClassMetadata $class
|
||||
* @param object $entity
|
||||
* @param array $data
|
||||
*
|
||||
* @todo The "$id" generation is the same of UnitOfWork#createEntity. Remove this duplication somehow
|
||||
*/
|
||||
protected function registerManaged(ClassMetadata $class, $entity, array $data)
|
||||
{
|
||||
if ($class->isIdentifierComposite) {
|
||||
$id = array();
|
||||
@ -311,6 +365,7 @@ abstract class AbstractHydrator
|
||||
$id = array($class->identifier[0] => $data[$class->identifier[0]]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->_em->getUnitOfWork()->registerManaged($entity, $id, $data);
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,14 @@ use PDO, Doctrine\DBAL\Connection, Doctrine\ORM\Mapping\ClassMetadata;
|
||||
* The ArrayHydrator produces a nested array "graph" that is often (not always)
|
||||
* interchangeable with the corresponding object graph for read-only access.
|
||||
*
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 1.0
|
||||
* @author Guilherme Blanco <guilhermeblanoc@hotmail.com>
|
||||
*
|
||||
* @todo General behavior is "wrong" if you define an alias to selected IdentificationVariable.
|
||||
* Example: SELECT u AS user FROM User u
|
||||
* The result should contains an array where each array index is an array: array('user' => [User object])
|
||||
* Problem must be solved somehow by removing the isMixed in ResultSetMapping
|
||||
*/
|
||||
class ArrayHydrator extends AbstractHydrator
|
||||
{
|
||||
@ -38,45 +44,55 @@ class ArrayHydrator extends AbstractHydrator
|
||||
private $_idTemplate = array();
|
||||
private $_resultCounter = 0;
|
||||
|
||||
/** @override */
|
||||
protected function _prepare()
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function prepare()
|
||||
{
|
||||
$this->_isSimpleQuery = count($this->_rsm->aliasMap) <= 1;
|
||||
$this->_identifierMap = array();
|
||||
$this->_isSimpleQuery = count($this->_rsm->aliasMap) <= 1;
|
||||
$this->_identifierMap = array();
|
||||
$this->_resultPointers = array();
|
||||
$this->_idTemplate = array();
|
||||
$this->_resultCounter = 0;
|
||||
$this->_idTemplate = array();
|
||||
$this->_resultCounter = 0;
|
||||
|
||||
foreach ($this->_rsm->aliasMap as $dqlAlias => $className) {
|
||||
$this->_identifierMap[$dqlAlias] = array();
|
||||
$this->_identifierMap[$dqlAlias] = array();
|
||||
$this->_resultPointers[$dqlAlias] = array();
|
||||
$this->_idTemplate[$dqlAlias] = '';
|
||||
$this->_idTemplate[$dqlAlias] = '';
|
||||
}
|
||||
}
|
||||
|
||||
/** @override */
|
||||
protected function _hydrateAll()
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function hydrateAllData()
|
||||
{
|
||||
$result = array();
|
||||
$cache = array();
|
||||
$cache = array();
|
||||
|
||||
while ($data = $this->_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$this->_hydrateRow($data, $cache, $result);
|
||||
$this->hydrateRowData($data, $cache, $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/** @override */
|
||||
protected function _hydrateRow(array $data, array &$cache, array &$result)
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function hydrateRowData(array $row, array &$cache, array &$result)
|
||||
{
|
||||
// 1) Initialize
|
||||
$id = $this->_idTemplate; // initialize the id-memory
|
||||
$nonemptyComponents = array();
|
||||
$rowData = $this->_gatherRowData($data, $cache, $id, $nonemptyComponents);
|
||||
$rowData = $this->gatherRowData($row, $cache, $id, $nonemptyComponents);
|
||||
|
||||
// Extract scalar values. They're appended at the end.
|
||||
if (isset($rowData['scalars'])) {
|
||||
$scalars = $rowData['scalars'];
|
||||
|
||||
unset($rowData['scalars']);
|
||||
|
||||
if (empty($rowData)) {
|
||||
++$this->_resultCounter;
|
||||
}
|
||||
@ -90,7 +106,7 @@ class ArrayHydrator extends AbstractHydrator
|
||||
// It's a joined result
|
||||
|
||||
$parent = $this->_rsm->parentAliasMap[$dqlAlias];
|
||||
$path = $parent . '.' . $dqlAlias;
|
||||
$path = $parent . '.' . $dqlAlias;
|
||||
|
||||
// missing parent data, skipping as RIGHT JOIN hydration is not supported.
|
||||
if ( ! isset($nonemptyComponents[$parent]) ) {
|
||||
@ -109,39 +125,41 @@ class ArrayHydrator extends AbstractHydrator
|
||||
unset($this->_resultPointers[$dqlAlias]); // Ticket #1228
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
$relationAlias = $this->_rsm->relationMap[$dqlAlias];
|
||||
$relation = $this->_getClassMetadata($this->_rsm->aliasMap[$parent])->associationMappings[$relationAlias];
|
||||
$relation = $this->getClassMetadata($this->_rsm->aliasMap[$parent])->associationMappings[$relationAlias];
|
||||
|
||||
// Check the type of the relation (many or single-valued)
|
||||
if ( ! ($relation['type'] & ClassMetadata::TO_ONE)) {
|
||||
$oneToOne = false;
|
||||
|
||||
if (isset($nonemptyComponents[$dqlAlias])) {
|
||||
if ( ! isset($baseElement[$relationAlias])) {
|
||||
$baseElement[$relationAlias] = array();
|
||||
}
|
||||
|
||||
$indexExists = isset($this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]]);
|
||||
$index = $indexExists ? $this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] : false;
|
||||
|
||||
$indexExists = isset($this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]]);
|
||||
$index = $indexExists ? $this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] : false;
|
||||
$indexIsValid = $index !== false ? isset($baseElement[$relationAlias][$index]) : false;
|
||||
|
||||
|
||||
if ( ! $indexExists || ! $indexIsValid) {
|
||||
$element = $data;
|
||||
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
|
||||
$field = $this->_rsm->indexByMap[$dqlAlias];
|
||||
$baseElement[$relationAlias][$element[$field]] = $element;
|
||||
$baseElement[$relationAlias][$row[$this->_rsm->indexByMap[$dqlAlias]]] = $element;
|
||||
} else {
|
||||
$baseElement[$relationAlias][] = $element;
|
||||
}
|
||||
|
||||
end($baseElement[$relationAlias]);
|
||||
$this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] =
|
||||
key($baseElement[$relationAlias]);
|
||||
|
||||
$this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] = key($baseElement[$relationAlias]);
|
||||
}
|
||||
} else if ( ! isset($baseElement[$relationAlias])) {
|
||||
$baseElement[$relationAlias] = array();
|
||||
}
|
||||
} else {
|
||||
$oneToOne = true;
|
||||
|
||||
if ( ! isset($nonemptyComponents[$dqlAlias]) && ! isset($baseElement[$relationAlias])) {
|
||||
$baseElement[$relationAlias] = null;
|
||||
} else if ( ! isset($baseElement[$relationAlias])) {
|
||||
@ -157,43 +175,42 @@ class ArrayHydrator extends AbstractHydrator
|
||||
|
||||
} else {
|
||||
// It's a root result element
|
||||
|
||||
|
||||
$this->_rootAliases[$dqlAlias] = true; // Mark as root
|
||||
$entityKey = $this->_rsm->entityMappings[$dqlAlias] ?: 0;
|
||||
|
||||
// if this row has a NULL value for the root result id then make it a null result.
|
||||
if ( ! isset($nonemptyComponents[$dqlAlias]) ) {
|
||||
if ($this->_rsm->isMixed) {
|
||||
$result[] = array(0 => null);
|
||||
$result[] = array($entityKey => null);
|
||||
} else {
|
||||
$result[] = null;
|
||||
}
|
||||
$resultKey = $this->_resultCounter;
|
||||
++$this->_resultCounter;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Check for an existing element
|
||||
if ($this->_isSimpleQuery || ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) {
|
||||
$element = $rowData[$dqlAlias];
|
||||
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
|
||||
$field = $this->_rsm->indexByMap[$dqlAlias];
|
||||
if ($this->_rsm->isMixed) {
|
||||
$result[] = array($element[$field] => $element);
|
||||
++$this->_resultCounter;
|
||||
} else {
|
||||
$result[$element[$field]] = $element;
|
||||
}
|
||||
} else {
|
||||
if ($this->_rsm->isMixed) {
|
||||
$result[] = array($element);
|
||||
++$this->_resultCounter;
|
||||
} else {
|
||||
$result[] = $element;
|
||||
}
|
||||
if ($this->_rsm->isMixed) {
|
||||
$element = array($entityKey => $element);
|
||||
}
|
||||
end($result);
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = key($result);
|
||||
|
||||
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
|
||||
$resultKey = $row[$this->_rsm->indexByMap[$dqlAlias]];
|
||||
$result[$resultKey] = $element;
|
||||
} else {
|
||||
$resultKey = $this->_resultCounter;
|
||||
$result[] = $element;
|
||||
++$this->_resultCounter;
|
||||
}
|
||||
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $resultKey;
|
||||
} else {
|
||||
$index = $this->_identifierMap[$dqlAlias][$id[$dqlAlias]];
|
||||
$resultKey = $index;
|
||||
/*if ($this->_rsm->isMixed) {
|
||||
$result[] =& $result[$index];
|
||||
++$this->_resultCounter;
|
||||
@ -205,8 +222,17 @@ class ArrayHydrator extends AbstractHydrator
|
||||
|
||||
// Append scalar values to mixed result sets
|
||||
if (isset($scalars)) {
|
||||
if ( ! isset($resultKey) ) {
|
||||
// this only ever happens when no object is fetched (scalar result only)
|
||||
if (isset($this->_rsm->indexByMap['scalars'])) {
|
||||
$resultKey = $row[$this->_rsm->indexByMap['scalars']];
|
||||
} else {
|
||||
$resultKey = $this->_resultCounter - 1;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($scalars as $name => $value) {
|
||||
$result[$this->_resultCounter - 1][$name] = $value;
|
||||
$result[$resultKey][$name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -224,28 +250,45 @@ class ArrayHydrator extends AbstractHydrator
|
||||
{
|
||||
if ($coll === null) {
|
||||
unset($this->_resultPointers[$dqlAlias]); // Ticket #1228
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($index !== false) {
|
||||
$this->_resultPointers[$dqlAlias] =& $coll[$index];
|
||||
|
||||
return;
|
||||
} else {
|
||||
if ($coll) {
|
||||
if ($oneToOne) {
|
||||
$this->_resultPointers[$dqlAlias] =& $coll;
|
||||
} else {
|
||||
end($coll);
|
||||
$this->_resultPointers[$dqlAlias] =& $coll[key($coll)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $coll) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($oneToOne) {
|
||||
$this->_resultPointers[$dqlAlias] =& $coll;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
end($coll);
|
||||
$this->_resultPointers[$dqlAlias] =& $coll[key($coll)];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private function _getClassMetadata($className)
|
||||
|
||||
/**
|
||||
* Retrieve ClassMetadata associated to entity class name.
|
||||
*
|
||||
* @param string $className
|
||||
*
|
||||
* @return Doctrine\ORM\Mapping\ClassMetadata
|
||||
*/
|
||||
private function getClassMetadata($className)
|
||||
{
|
||||
if ( ! isset($this->_ce[$className])) {
|
||||
$this->_ce[$className] = $this->_em->getClassMetadata($className);
|
||||
}
|
||||
|
||||
return $this->_ce[$className];
|
||||
}
|
||||
}
|
@ -8,10 +8,19 @@ class HydrationException extends \Doctrine\ORM\ORMException
|
||||
{
|
||||
return new self("The result returned by the query was not unique.");
|
||||
}
|
||||
|
||||
|
||||
public static function parentObjectOfRelationNotFound($alias, $parentAlias)
|
||||
{
|
||||
return new self("The parent object of entity result with alias '$alias' was not found."
|
||||
. " The parent alias is '$parentAlias'.");
|
||||
}
|
||||
|
||||
public static function emptyDiscriminatorValue($dqlAlias)
|
||||
{
|
||||
return new self("The DQL alias '" . $dqlAlias . "' contains an entity ".
|
||||
"of an inheritance hierachy with an empty discriminator value. This means " .
|
||||
"that the database contains inconsistent data with an empty " .
|
||||
"discriminator value in a table row."
|
||||
);
|
||||
}
|
||||
}
|
@ -29,9 +29,16 @@ use PDO,
|
||||
/**
|
||||
* The ObjectHydrator constructs an object graph out of an SQL result set.
|
||||
*
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
* @author Guilherme Blanco <guilhermeblanoc@hotmail.com>
|
||||
*
|
||||
* @internal Highly performance-sensitive code.
|
||||
*
|
||||
* @todo General behavior is "wrong" if you define an alias to selected IdentificationVariable.
|
||||
* Example: SELECT u AS user FROM User u
|
||||
* The result should contains an array where each array index is an array: array('user' => [User object])
|
||||
* Problem must be solved somehow by removing the isMixed in ResultSetMapping
|
||||
*/
|
||||
class ObjectHydrator extends AbstractHydrator
|
||||
{
|
||||
@ -53,57 +60,72 @@ class ObjectHydrator extends AbstractHydrator
|
||||
|
||||
|
||||
/** @override */
|
||||
protected function _prepare()
|
||||
protected function prepare()
|
||||
{
|
||||
$this->_identifierMap =
|
||||
$this->_resultPointers =
|
||||
$this->_idTemplate = array();
|
||||
|
||||
$this->_resultCounter = 0;
|
||||
if (!isset($this->_hints['deferEagerLoad'])) {
|
||||
|
||||
if ( ! isset($this->_hints['deferEagerLoad'])) {
|
||||
$this->_hints['deferEagerLoad'] = true;
|
||||
}
|
||||
|
||||
foreach ($this->_rsm->aliasMap as $dqlAlias => $className) {
|
||||
$this->_identifierMap[$dqlAlias] = array();
|
||||
$this->_idTemplate[$dqlAlias] = '';
|
||||
$class = $this->_em->getClassMetadata($className);
|
||||
$this->_idTemplate[$dqlAlias] = '';
|
||||
|
||||
if ( ! isset($this->_ce[$className])) {
|
||||
$this->_ce[$className] = $class;
|
||||
$this->_ce[$className] = $this->_em->getClassMetadata($className);
|
||||
}
|
||||
|
||||
// Remember which associations are "fetch joined", so that we know where to inject
|
||||
// collection stubs or proxies and where not.
|
||||
if (isset($this->_rsm->relationMap[$dqlAlias])) {
|
||||
if ( ! isset($this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]])) {
|
||||
throw HydrationException::parentObjectOfRelationNotFound($dqlAlias, $this->_rsm->parentAliasMap[$dqlAlias]);
|
||||
if ( ! isset($this->_rsm->relationMap[$dqlAlias])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! isset($this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]])) {
|
||||
throw HydrationException::parentObjectOfRelationNotFound($dqlAlias, $this->_rsm->parentAliasMap[$dqlAlias]);
|
||||
}
|
||||
|
||||
$sourceClassName = $this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]];
|
||||
$sourceClass = $this->_getClassMetadata($sourceClassName);
|
||||
$assoc = $sourceClass->associationMappings[$this->_rsm->relationMap[$dqlAlias]];
|
||||
|
||||
$this->_hints['fetched'][$sourceClassName][$assoc['fieldName']] = true;
|
||||
|
||||
if ($sourceClass->subClasses) {
|
||||
foreach ($sourceClass->subClasses as $sourceSubclassName) {
|
||||
$this->_hints['fetched'][$sourceSubclassName][$assoc['fieldName']] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($assoc['type'] === ClassMetadata::MANY_TO_MANY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Mark any non-collection opposite sides as fetched, too.
|
||||
if ($assoc['mappedBy']) {
|
||||
$this->_hints['fetched'][$className][$assoc['mappedBy']] = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($assoc['inversedBy']) {
|
||||
$class = $this->_ce[$className];
|
||||
$inverseAssoc = $class->associationMappings[$assoc['inversedBy']];
|
||||
|
||||
if ( ! ($inverseAssoc['type'] & ClassMetadata::TO_ONE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sourceClassName = $this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]];
|
||||
$sourceClass = $this->_getClassMetadata($sourceClassName);
|
||||
$assoc = $sourceClass->associationMappings[$this->_rsm->relationMap[$dqlAlias]];
|
||||
$this->_hints['fetched'][$sourceClassName][$assoc['fieldName']] = true;
|
||||
if ($sourceClass->subClasses) {
|
||||
foreach ($sourceClass->subClasses as $sourceSubclassName) {
|
||||
$this->_hints['fetched'][$sourceSubclassName][$assoc['fieldName']] = true;
|
||||
}
|
||||
}
|
||||
if ($assoc['type'] != ClassMetadata::MANY_TO_MANY) {
|
||||
// Mark any non-collection opposite sides as fetched, too.
|
||||
if ($assoc['mappedBy']) {
|
||||
$this->_hints['fetched'][$className][$assoc['mappedBy']] = true;
|
||||
} else {
|
||||
if ($assoc['inversedBy']) {
|
||||
$inverseAssoc = $class->associationMappings[$assoc['inversedBy']];
|
||||
if ($inverseAssoc['type'] & ClassMetadata::TO_ONE) {
|
||||
$this->_hints['fetched'][$className][$inverseAssoc['fieldName']] = true;
|
||||
if ($class->subClasses) {
|
||||
foreach ($class->subClasses as $targetSubclassName) {
|
||||
$this->_hints['fetched'][$targetSubclassName][$inverseAssoc['fieldName']] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->_hints['fetched'][$className][$inverseAssoc['fieldName']] = true;
|
||||
|
||||
if ($class->subClasses) {
|
||||
foreach ($class->subClasses as $targetSubclassName) {
|
||||
$this->_hints['fetched'][$targetSubclassName][$inverseAssoc['fieldName']] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -113,11 +135,12 @@ class ObjectHydrator extends AbstractHydrator
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _cleanup()
|
||||
protected function cleanup()
|
||||
{
|
||||
$eagerLoad = (isset($this->_hints['deferEagerLoad'])) && $this->_hints['deferEagerLoad'] == true;
|
||||
|
||||
parent::_cleanup();
|
||||
parent::cleanup();
|
||||
|
||||
$this->_identifierMap =
|
||||
$this->_initializedCollections =
|
||||
$this->_existingCollections =
|
||||
@ -131,13 +154,13 @@ class ObjectHydrator extends AbstractHydrator
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _hydrateAll()
|
||||
protected function hydrateAllData()
|
||||
{
|
||||
$result = array();
|
||||
$cache = array();
|
||||
$cache = array();
|
||||
|
||||
while ($row = $this->_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$this->_hydrateRow($row, $cache, $result);
|
||||
$this->hydrateRowData($row, $cache, $result);
|
||||
}
|
||||
|
||||
// Take snapshots from all newly initialized collections
|
||||
@ -156,31 +179,34 @@ class ObjectHydrator extends AbstractHydrator
|
||||
*/
|
||||
private function _initRelatedCollection($entity, $class, $fieldName)
|
||||
{
|
||||
$oid = spl_object_hash($entity);
|
||||
$oid = spl_object_hash($entity);
|
||||
$relation = $class->associationMappings[$fieldName];
|
||||
$value = $class->reflFields[$fieldName]->getValue($entity);
|
||||
|
||||
$value = $class->reflFields[$fieldName]->getValue($entity);
|
||||
if ($value === null) {
|
||||
$value = new ArrayCollection;
|
||||
}
|
||||
|
||||
if ( ! $value instanceof PersistentCollection) {
|
||||
$value = new PersistentCollection(
|
||||
$this->_em,
|
||||
$this->_ce[$relation['targetEntity']],
|
||||
$value
|
||||
$this->_em, $this->_ce[$relation['targetEntity']], $value
|
||||
);
|
||||
$value->setOwner($entity, $relation);
|
||||
|
||||
$class->reflFields[$fieldName]->setValue($entity, $value);
|
||||
$this->_uow->setOriginalEntityProperty($oid, $fieldName, $value);
|
||||
|
||||
$this->_initializedCollections[$oid . $fieldName] = $value;
|
||||
} else if (isset($this->_hints[Query::HINT_REFRESH]) ||
|
||||
isset($this->_hints['fetched'][$class->name][$fieldName]) &&
|
||||
! $value->isInitialized()) {
|
||||
} else if (
|
||||
isset($this->_hints[Query::HINT_REFRESH]) ||
|
||||
isset($this->_hints['fetched'][$class->name][$fieldName]) &&
|
||||
! $value->isInitialized()
|
||||
) {
|
||||
// Is already PersistentCollection, but either REFRESH or FETCH-JOIN and UNINITIALIZED!
|
||||
$value->setDirty(false);
|
||||
$value->setInitialized(true);
|
||||
$value->unwrap()->clear();
|
||||
|
||||
$this->_initializedCollections[$oid . $fieldName] = $value;
|
||||
} else {
|
||||
// Is already PersistentCollection, and DON'T REFRESH or FETCH-JOIN!
|
||||
@ -200,15 +226,21 @@ class ObjectHydrator extends AbstractHydrator
|
||||
private function _getEntity(array $data, $dqlAlias)
|
||||
{
|
||||
$className = $this->_rsm->aliasMap[$dqlAlias];
|
||||
|
||||
if (isset($this->_rsm->discriminatorColumns[$dqlAlias])) {
|
||||
$discrColumn = $this->_rsm->metaMappings[$this->_rsm->discriminatorColumns[$dqlAlias]];
|
||||
|
||||
if ($data[$discrColumn] === "") {
|
||||
throw HydrationException::emptyDiscriminatorValue($dqlAlias);
|
||||
}
|
||||
|
||||
$className = $this->_ce[$className]->discriminatorMap[$data[$discrColumn]];
|
||||
|
||||
unset($data[$discrColumn]);
|
||||
}
|
||||
|
||||
if (isset($this->_hints[Query::HINT_REFRESH_ENTITY]) && isset($this->_rootAliases[$dqlAlias])) {
|
||||
$class = $this->_ce[$className];
|
||||
$this->registerManaged($class, $this->_hints[Query::HINT_REFRESH_ENTITY], $data);
|
||||
$this->registerManaged($this->_ce[$className], $this->_hints[Query::HINT_REFRESH_ENTITY], $data);
|
||||
}
|
||||
|
||||
return $this->_uow->createEntity($className, $data, $this->_hints);
|
||||
@ -218,6 +250,7 @@ class ObjectHydrator extends AbstractHydrator
|
||||
{
|
||||
// TODO: Abstract this code and UnitOfWork::createEntity() equivalent?
|
||||
$class = $this->_ce[$className];
|
||||
|
||||
/* @var $class ClassMetadata */
|
||||
if ($class->isIdentifierComposite) {
|
||||
$idHash = '';
|
||||
@ -249,6 +282,7 @@ class ObjectHydrator extends AbstractHydrator
|
||||
if ( ! isset($this->_ce[$className])) {
|
||||
$this->_ce[$className] = $this->_em->getClassMetadata($className);
|
||||
}
|
||||
|
||||
return $this->_ce[$className];
|
||||
}
|
||||
|
||||
@ -273,13 +307,13 @@ class ObjectHydrator extends AbstractHydrator
|
||||
* @param array $cache The cache to use.
|
||||
* @param array $result The result array to fill.
|
||||
*/
|
||||
protected function _hydrateRow(array $data, array &$cache, array &$result)
|
||||
protected function hydrateRowData(array $row, array &$cache, array &$result)
|
||||
{
|
||||
// Initialize
|
||||
$id = $this->_idTemplate; // initialize the id-memory
|
||||
$nonemptyComponents = array();
|
||||
// Split the row data into chunks of class data.
|
||||
$rowData = $this->_gatherRowData($data, $cache, $id, $nonemptyComponents);
|
||||
$rowData = $this->gatherRowData($row, $cache, $id, $nonemptyComponents);
|
||||
|
||||
// Extract scalar values. They're appended at the end.
|
||||
if (isset($rowData['scalars'])) {
|
||||
@ -352,8 +386,7 @@ class ObjectHydrator extends AbstractHydrator
|
||||
$element = $this->_getEntity($data, $dqlAlias);
|
||||
|
||||
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
|
||||
$field = $this->_rsm->indexByMap[$dqlAlias];
|
||||
$indexValue = $this->_ce[$entityName]->reflFields[$field]->getValue($element);
|
||||
$indexValue = $row[$this->_rsm->indexByMap[$dqlAlias]];
|
||||
$reflFieldValue->hydrateSet($indexValue, $element);
|
||||
$this->_identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]] = $indexValue;
|
||||
} else {
|
||||
@ -380,6 +413,7 @@ class ObjectHydrator extends AbstractHydrator
|
||||
$reflField->setValue($parentObject, $element);
|
||||
$this->_uow->setOriginalEntityProperty($oid, $relationField, $element);
|
||||
$targetClass = $this->_ce[$relation['targetEntity']];
|
||||
|
||||
if ($relation['isOwningSide']) {
|
||||
//TODO: Just check hints['fetched'] here?
|
||||
// If there is an inverse mapping on the target class its bidirectional
|
||||
@ -410,14 +444,16 @@ class ObjectHydrator extends AbstractHydrator
|
||||
} else {
|
||||
// PATH C: Its a root result element
|
||||
$this->_rootAliases[$dqlAlias] = true; // Mark as root alias
|
||||
$entityKey = $this->_rsm->entityMappings[$dqlAlias] ?: 0;
|
||||
|
||||
// if this row has a NULL value for the root result id then make it a null result.
|
||||
if ( ! isset($nonemptyComponents[$dqlAlias]) ) {
|
||||
if ($this->_rsm->isMixed) {
|
||||
$result[] = array(0 => null);
|
||||
$result[] = array($entityKey => null);
|
||||
} else {
|
||||
$result[] = null;
|
||||
}
|
||||
$resultKey = $this->_resultCounter;
|
||||
++$this->_resultCounter;
|
||||
continue;
|
||||
}
|
||||
@ -425,35 +461,31 @@ class ObjectHydrator extends AbstractHydrator
|
||||
// check for existing result from the iterations before
|
||||
if ( ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) {
|
||||
$element = $this->_getEntity($rowData[$dqlAlias], $dqlAlias);
|
||||
if ($this->_rsm->isMixed) {
|
||||
$element = array($entityKey => $element);
|
||||
}
|
||||
|
||||
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
|
||||
$field = $this->_rsm->indexByMap[$dqlAlias];
|
||||
$key = $this->_ce[$entityName]->reflFields[$field]->getValue($element);
|
||||
if ($this->_rsm->isMixed) {
|
||||
$element = array($key => $element);
|
||||
$result[] = $element;
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $this->_resultCounter;
|
||||
++$this->_resultCounter;
|
||||
} else {
|
||||
$result[$key] = $element;
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $key;
|
||||
}
|
||||
$resultKey = $row[$this->_rsm->indexByMap[$dqlAlias]];
|
||||
|
||||
if (isset($this->_hints['collection'])) {
|
||||
$this->_hints['collection']->hydrateSet($key, $element);
|
||||
$this->_hints['collection']->hydrateSet($resultKey, $element);
|
||||
}
|
||||
|
||||
$result[$resultKey] = $element;
|
||||
} else {
|
||||
if ($this->_rsm->isMixed) {
|
||||
$element = array(0 => $element);
|
||||
}
|
||||
$result[] = $element;
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $this->_resultCounter;
|
||||
$resultKey = $this->_resultCounter;
|
||||
++$this->_resultCounter;
|
||||
|
||||
if (isset($this->_hints['collection'])) {
|
||||
$this->_hints['collection']->hydrateAdd($element);
|
||||
}
|
||||
|
||||
$result[] = $element;
|
||||
}
|
||||
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $resultKey;
|
||||
|
||||
// Update result pointer
|
||||
$this->_resultPointers[$dqlAlias] = $element;
|
||||
|
||||
@ -461,6 +493,7 @@ class ObjectHydrator extends AbstractHydrator
|
||||
// Update result pointer
|
||||
$index = $this->_identifierMap[$dqlAlias][$id[$dqlAlias]];
|
||||
$this->_resultPointers[$dqlAlias] = $result[$index];
|
||||
$resultKey = $index;
|
||||
/*if ($this->_rsm->isMixed) {
|
||||
$result[] = $result[$index];
|
||||
++$this->_resultCounter;
|
||||
@ -471,8 +504,16 @@ class ObjectHydrator extends AbstractHydrator
|
||||
|
||||
// Append scalar values to mixed result sets
|
||||
if (isset($scalars)) {
|
||||
if ( ! isset($resultKey) ) {
|
||||
if (isset($this->_rsm->indexByMap['scalars'])) {
|
||||
$resultKey = $row[$this->_rsm->indexByMap['scalars']];
|
||||
} else {
|
||||
$resultKey = $this->_resultCounter - 1;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($scalars as $name => $value) {
|
||||
$result[$this->_resultCounter - 1][$name] = $value;
|
||||
$result[$resultKey][$name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,25 +26,32 @@ use Doctrine\DBAL\Connection;
|
||||
* The created result is almost the same as a regular SQL result set, except
|
||||
* that column names are mapped to field names and data type conversions take place.
|
||||
*
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
*/
|
||||
class ScalarHydrator extends AbstractHydrator
|
||||
{
|
||||
/** @override */
|
||||
protected function _hydrateAll()
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function hydrateAllData()
|
||||
{
|
||||
$result = array();
|
||||
$cache = array();
|
||||
$cache = array();
|
||||
|
||||
while ($data = $this->_stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||
$result[] = $this->_gatherScalarRowData($data, $cache);
|
||||
$this->hydrateRowData($data, $cache, $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/** @override */
|
||||
protected function _hydrateRow(array $data, array &$cache, array &$result)
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function hydrateRowData(array $data, array &$cache, array &$result)
|
||||
{
|
||||
$result[] = $this->_gatherScalarRowData($data, $cache);
|
||||
$result[] = $this->gatherScalarRowData($data, $cache);
|
||||
}
|
||||
}
|
@ -17,7 +17,6 @@
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
|
||||
namespace Doctrine\ORM\Internal\Hydration;
|
||||
|
||||
use \PDO;
|
||||
@ -32,15 +31,21 @@ class SimpleObjectHydrator extends AbstractHydrator
|
||||
*/
|
||||
private $class;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $declaringClasses = array();
|
||||
|
||||
protected function _hydrateAll()
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function hydrateAllData()
|
||||
{
|
||||
$result = array();
|
||||
$cache = array();
|
||||
|
||||
while ($row = $this->_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$this->_hydrateRow($row, $cache, $result);
|
||||
$this->hydrateRowData($row, $cache, $result);
|
||||
}
|
||||
|
||||
$this->_em->getUnitOfWork()->triggerEagerLoads();
|
||||
@ -48,77 +53,71 @@ class SimpleObjectHydrator extends AbstractHydrator
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function _prepare()
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function prepare()
|
||||
{
|
||||
if (count($this->_rsm->aliasMap) == 1) {
|
||||
$this->class = $this->_em->getClassMetadata(reset($this->_rsm->aliasMap));
|
||||
if ($this->class->inheritanceType !== ClassMetadata::INHERITANCE_TYPE_NONE) {
|
||||
foreach ($this->_rsm->declaringClasses AS $column => $class) {
|
||||
$this->declaringClasses[$column] = $this->_em->getClassMetadata($class);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new \RuntimeException("Cannot use SimpleObjectHydrator with a ResultSetMapping not containing exactly one object result.");
|
||||
if (count($this->_rsm->aliasMap) !== 1) {
|
||||
throw new \RuntimeException("Cannot use SimpleObjectHydrator with a ResultSetMapping that contains more than one object result.");
|
||||
}
|
||||
|
||||
if ($this->_rsm->scalarMappings) {
|
||||
throw new \RuntimeException("Cannot use SimpleObjectHydrator with a ResultSetMapping that contains scalar mappings.");
|
||||
}
|
||||
|
||||
$this->class = $this->_em->getClassMetadata(reset($this->_rsm->aliasMap));
|
||||
|
||||
// We only need to add declaring classes if we have inheritance.
|
||||
if ($this->class->inheritanceType === ClassMetadata::INHERITANCE_TYPE_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->_rsm->declaringClasses AS $column => $class) {
|
||||
$this->declaringClasses[$column] = $this->_em->getClassMetadata($class);
|
||||
}
|
||||
}
|
||||
|
||||
protected function _hydrateRow(array $sqlResult, array &$cache, array &$result)
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function hydrateRowData(array $sqlResult, array &$cache, array &$result)
|
||||
{
|
||||
$data = array();
|
||||
if ($this->class->inheritanceType == ClassMetadata::INHERITANCE_TYPE_NONE) {
|
||||
foreach ($sqlResult as $column => $value) {
|
||||
|
||||
if (!isset($cache[$column])) {
|
||||
if (isset($this->_rsm->fieldMappings[$column])) {
|
||||
$cache[$column]['name'] = $this->_rsm->fieldMappings[$column];
|
||||
$cache[$column]['field'] = true;
|
||||
} else {
|
||||
$cache[$column]['name'] = $this->_rsm->metaMappings[$column];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($cache[$column]['field'])) {
|
||||
$value = Type::getType($this->class->fieldMappings[$cache[$column]['name']]['type'])
|
||||
->convertToPHPValue($value, $this->_platform);
|
||||
}
|
||||
$data[$cache[$column]['name']] = $value;
|
||||
}
|
||||
$entityName = $this->class->name;
|
||||
} else {
|
||||
$entityName = $this->class->name;
|
||||
$data = array();
|
||||
|
||||
// We need to find the correct entity class name if we have inheritance in resultset
|
||||
if ($this->class->inheritanceType !== ClassMetadata::INHERITANCE_TYPE_NONE) {
|
||||
$discrColumnName = $this->_platform->getSQLResultCasing($this->class->discriminatorColumn['name']);
|
||||
|
||||
if ($sqlResult[$discrColumnName] === '') {
|
||||
throw HydrationException::emptyDiscriminatorValue(key($this->_rsm->aliasMap));
|
||||
}
|
||||
|
||||
$entityName = $this->class->discriminatorMap[$sqlResult[$discrColumnName]];
|
||||
|
||||
unset($sqlResult[$discrColumnName]);
|
||||
foreach ($sqlResult as $column => $value) {
|
||||
if (!isset($cache[$column])) {
|
||||
if (isset($this->_rsm->fieldMappings[$column])) {
|
||||
$field = $this->_rsm->fieldMappings[$column];
|
||||
$class = $this->declaringClasses[$column];
|
||||
if ($class->name == $entityName || is_subclass_of($entityName, $class->name)) {
|
||||
$cache[$column]['name'] = $field;
|
||||
$cache[$column]['class'] = $class;
|
||||
}
|
||||
} else if (isset($this->_rsm->relationMap[$column])) {
|
||||
if ($this->_rsm->relationMap[$column] == $entityName || is_subclass_of($entityName, $this->_rsm->relationMap[$column])) {
|
||||
$cache[$column]['name'] = $field;
|
||||
}
|
||||
} else {
|
||||
$cache[$column]['name'] = $this->_rsm->metaMappings[$column];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($sqlResult as $column => $value) {
|
||||
// Hydrate column information if not yet present
|
||||
if ( ! isset($cache[$column])) {
|
||||
if (($info = $this->hydrateColumnInfo($entityName, $column)) === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$cache[$column] = $info;
|
||||
}
|
||||
|
||||
if (isset($cache[$column]['class'])) {
|
||||
$value = Type::getType($cache[$column]['class']->fieldMappings[$cache[$column]['name']]['type'])
|
||||
->convertToPHPValue($value, $this->_platform);
|
||||
}
|
||||
|
||||
// the second and part is to prevent overwrites in case of multiple
|
||||
// inheritance classes using the same property name (See AbstractHydrator)
|
||||
if (isset($cache[$column]) && (!isset($data[$cache[$column]['name']]) || $value !== null)) {
|
||||
$data[$cache[$column]['name']] = $value;
|
||||
}
|
||||
// Convert field to a valid PHP value
|
||||
if (isset($cache[$column]['field'])) {
|
||||
$type = Type::getType($cache[$column]['class']->fieldMappings[$cache[$column]['name']]['type']);
|
||||
$value = $type->convertToPHPValue($value, $this->_platform);
|
||||
}
|
||||
|
||||
// Prevent overwrite in case of inherit classes using same property name (See AbstractHydrator)
|
||||
if (isset($cache[$column]) && ( ! isset($data[$cache[$column]['name']]) || $value !== null)) {
|
||||
$data[$cache[$column]['name']] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,4 +127,52 @@ class SimpleObjectHydrator extends AbstractHydrator
|
||||
|
||||
$result[] = $this->_em->getUnitOfWork()->createEntity($entityName, $data, $this->_hints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve column information form ResultSetMapping.
|
||||
*
|
||||
* @param string $entityName
|
||||
* @param string $column
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function hydrateColumnInfo($entityName, $column)
|
||||
{
|
||||
switch (true) {
|
||||
case (isset($this->_rsm->fieldMappings[$column])):
|
||||
$class = isset($this->declaringClasses[$column])
|
||||
? $this->declaringClasses[$column]
|
||||
: $this->class;
|
||||
|
||||
// If class is not part of the inheritance, ignore
|
||||
if ( ! ($class->name === $entityName || is_subclass_of($entityName, $class->name))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return array(
|
||||
'class' => $class,
|
||||
'name' => $this->_rsm->fieldMappings[$column],
|
||||
'field' => true,
|
||||
);
|
||||
|
||||
case (isset($this->_rsm->relationMap[$column])):
|
||||
$class = isset($this->_rsm->relationMap[$column])
|
||||
? $this->_rsm->relationMap[$column]
|
||||
: $this->class;
|
||||
|
||||
// If class is not self referencing, ignore
|
||||
if ( ! ($class === $entityName || is_subclass_of($entityName, $class))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO: Decide what to do with associations. It seems original code is incomplete.
|
||||
// One solution is to load the association, but it might require extra efforts.
|
||||
return array('name' => $column);
|
||||
|
||||
default:
|
||||
return array(
|
||||
'name' => $this->_rsm->metaMappings[$column]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -19,30 +19,37 @@
|
||||
|
||||
namespace Doctrine\ORM\Internal\Hydration;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\Connection,
|
||||
Doctrine\ORM\NoResultException,
|
||||
Doctrine\ORM\NonUniqueResultException;
|
||||
|
||||
/**
|
||||
* Hydrator that hydrates a single scalar value from the result set.
|
||||
*
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
*/
|
||||
class SingleScalarHydrator extends AbstractHydrator
|
||||
{
|
||||
/** @override */
|
||||
protected function _hydrateAll()
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function hydrateAllData()
|
||||
{
|
||||
$cache = array();
|
||||
$result = $this->_stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
$num = count($result);
|
||||
|
||||
if ($num == 0) {
|
||||
throw new \Doctrine\ORM\NoResultException;
|
||||
} else if ($num > 1 || count($result[key($result)]) > 1) {
|
||||
throw new \Doctrine\ORM\NonUniqueResultException;
|
||||
$data = $this->_stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
$numRows = count($data);
|
||||
|
||||
if ($numRows === 0) {
|
||||
throw new NoResultException();
|
||||
}
|
||||
|
||||
$result = $this->_gatherScalarRowData($result[key($result)], $cache);
|
||||
if ($numRows > 1 || count($data[key($data)]) > 1) {
|
||||
throw new NonUniqueResultException();
|
||||
}
|
||||
|
||||
$cache = array();
|
||||
$result = $this->gatherScalarRowData($data[key($data)], $cache);
|
||||
|
||||
return array_shift($result);
|
||||
}
|
||||
|
@ -312,6 +312,10 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
||||
if ($parent && $parent->containsForeignIdentifier) {
|
||||
$class->containsForeignIdentifier = true;
|
||||
}
|
||||
|
||||
if ($parent && !empty ($parent->namedQueries)) {
|
||||
$this->addInheritedNamedQueries($class, $parent);
|
||||
}
|
||||
|
||||
$class->setParentClasses($visited);
|
||||
|
||||
@ -428,6 +432,25 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
||||
$subClass->addInheritedAssociationMapping($mapping);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds inherited named queries to the subclass mapping.
|
||||
*
|
||||
* @since 2.2
|
||||
* @param Doctrine\ORM\Mapping\ClassMetadata $subClass
|
||||
* @param Doctrine\ORM\Mapping\ClassMetadata $parentClass
|
||||
*/
|
||||
private function addInheritedNamedQueries(ClassMetadata $subClass, ClassMetadata $parentClass)
|
||||
{
|
||||
foreach ($parentClass->namedQueries as $name => $query) {
|
||||
if (!isset ($subClass->namedQueries[$name])) {
|
||||
$subClass->addNamedQuery(array(
|
||||
'name' => $query['name'],
|
||||
'query' => $query['query']
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Completes the ID generator mapping. If "auto" is specified we choose the generator
|
||||
|
@ -136,10 +136,6 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
* Identifies a many-to-one association.
|
||||
*/
|
||||
const MANY_TO_ONE = 2;
|
||||
/**
|
||||
* Combined bitmask for to-one (single-valued) associations.
|
||||
*/
|
||||
const TO_ONE = 3;
|
||||
/**
|
||||
* Identifies a one-to-many association.
|
||||
*/
|
||||
@ -148,6 +144,10 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
* 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.
|
||||
*/
|
||||
@ -685,7 +685,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
if ( ! isset($this->namedQueries[$queryName])) {
|
||||
throw MappingException::queryNotFound($this->name, $queryName);
|
||||
}
|
||||
return $this->namedQueries[$queryName];
|
||||
return $this->namedQueries[$queryName]['dql'];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1111,25 +1111,25 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
*/
|
||||
public function getIdentifierColumnNames()
|
||||
{
|
||||
if ($this->isIdentifierComposite) {
|
||||
$columnNames = array();
|
||||
foreach ($this->identifier as $idField) {
|
||||
if (isset($this->associationMappings[$idField])) {
|
||||
// no composite pk as fk entity assumption:
|
||||
$columnNames[] = $this->associationMappings[$idField]['joinColumns'][0]['name'];
|
||||
} else {
|
||||
$columnNames[] = $this->fieldMappings[$idField]['columnName'];
|
||||
}
|
||||
$columnNames = array();
|
||||
|
||||
foreach ($this->identifier as $idProperty) {
|
||||
if (isset($this->fieldMappings[$idProperty])) {
|
||||
$columnNames[] = $this->fieldMappings[$idProperty]['columnName'];
|
||||
|
||||
continue;
|
||||
}
|
||||
return $columnNames;
|
||||
} else if(isset($this->fieldMappings[$this->identifier[0]])) {
|
||||
return array($this->fieldMappings[$this->identifier[0]]['columnName']);
|
||||
} else {
|
||||
// no composite pk as fk entity assumption:
|
||||
return array($this->associationMappings[$this->identifier[0]]['joinColumns'][0]['name']);
|
||||
|
||||
// Association defined as Id field
|
||||
$joinColumns = $this->associationMappings[$idProperty]['joinColumns'];
|
||||
$assocColumnNames = array_map(function ($joinColumn) { return $joinColumn['name']; }, $joinColumns);
|
||||
|
||||
$columnNames = array_merge($columnNames, $assocColumnNames);
|
||||
}
|
||||
|
||||
return $columnNames;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the type of Id generator to use for the mapped class.
|
||||
*/
|
||||
@ -1448,8 +1448,15 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
if (isset($this->namedQueries[$queryMapping['name']])) {
|
||||
throw MappingException::duplicateQueryMapping($this->name, $queryMapping['name']);
|
||||
}
|
||||
$query = str_replace('__CLASS__', $this->name, $queryMapping['query']);
|
||||
$this->namedQueries[$queryMapping['name']] = $query;
|
||||
|
||||
$name = $queryMapping['name'];
|
||||
$query = $queryMapping['query'];
|
||||
$dql = str_replace('__CLASS__', $this->name, $query);
|
||||
$this->namedQueries[$name] = array(
|
||||
'name' => $name,
|
||||
'query' => $query,
|
||||
'dql' => $dql
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1504,14 +1511,16 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
/**
|
||||
* Stores the association mapping.
|
||||
*
|
||||
* @param AssociationMapping $assocMapping
|
||||
* @param array $assocMapping
|
||||
*/
|
||||
protected function _storeAssociationMapping(array $assocMapping)
|
||||
{
|
||||
$sourceFieldName = $assocMapping['fieldName'];
|
||||
|
||||
if (isset($this->fieldMappings[$sourceFieldName]) || isset($this->associationMappings[$sourceFieldName])) {
|
||||
throw MappingException::duplicateFieldMapping($this->name, $sourceFieldName);
|
||||
}
|
||||
|
||||
$this->associationMappings[$sourceFieldName] = $assocMapping;
|
||||
}
|
||||
|
||||
@ -1904,6 +1913,42 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the (possibly quoted) identifier column names for safe use in an SQL statement.
|
||||
*
|
||||
* @param AbstractPlatform $platform
|
||||
* @return array
|
||||
*/
|
||||
public function getQuotedIdentifierColumnNames($platform)
|
||||
{
|
||||
$quotedColumnNames = array();
|
||||
|
||||
foreach ($this->identifier as $idProperty) {
|
||||
if (isset($this->fieldMappings[$idProperty])) {
|
||||
$quotedColumnNames[] = isset($this->fieldMappings[$idProperty]['quoted'])
|
||||
? $platform->quoteIdentifier($this->fieldMappings[$idProperty]['columnName'])
|
||||
: $this->fieldMappings[$idProperty]['columnName'];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Association defined as Id field
|
||||
$joinColumns = $this->associationMappings[$idProperty]['joinColumns'];
|
||||
$assocQuotedColumnNames = array_map(
|
||||
function ($joinColumn) {
|
||||
return isset($joinColumn['quoted'])
|
||||
? $platform->quoteIdentifier($joinColumn['name'])
|
||||
: $joinColumn['name'];
|
||||
},
|
||||
$joinColumns
|
||||
);
|
||||
|
||||
$quotedColumnNames = array_merge($quotedColumnNames, $assocQuotedColumnNames);
|
||||
}
|
||||
|
||||
return $quotedColumnNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the (possibly quoted) column name of a mapped field for safe use
|
||||
* in an SQL statement.
|
||||
@ -1914,7 +1959,9 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
*/
|
||||
public function getQuotedColumnName($field, $platform)
|
||||
{
|
||||
return isset($this->fieldMappings[$field]['quoted']) ? $platform->quoteIdentifier($this->fieldMappings[$field]['columnName']) : $this->fieldMappings[$field]['columnName'];
|
||||
return isset($this->fieldMappings[$field]['quoted'])
|
||||
? $platform->quoteIdentifier($this->fieldMappings[$field]['columnName'])
|
||||
: $this->fieldMappings[$field]['columnName'];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -331,7 +331,7 @@ class AnnotationDriver implements Driver
|
||||
$mapping['inversedBy'] = $oneToOneAnnot->inversedBy;
|
||||
$mapping['cascade'] = $oneToOneAnnot->cascade;
|
||||
$mapping['orphanRemoval'] = $oneToOneAnnot->orphanRemoval;
|
||||
$mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToOneAnnot->fetch);
|
||||
$mapping['fetch'] = $this->getFetchMode($className, $oneToOneAnnot->fetch);
|
||||
$metadata->mapOneToOne($mapping);
|
||||
} else if ($oneToManyAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OneToMany')) {
|
||||
$mapping['mappedBy'] = $oneToManyAnnot->mappedBy;
|
||||
@ -339,7 +339,7 @@ class AnnotationDriver implements Driver
|
||||
$mapping['cascade'] = $oneToManyAnnot->cascade;
|
||||
$mapping['indexBy'] = $oneToManyAnnot->indexBy;
|
||||
$mapping['orphanRemoval'] = $oneToManyAnnot->orphanRemoval;
|
||||
$mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToManyAnnot->fetch);
|
||||
$mapping['fetch'] = $this->getFetchMode($className, $oneToManyAnnot->fetch);
|
||||
|
||||
if ($orderByAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OrderBy')) {
|
||||
$mapping['orderBy'] = $orderByAnnot->value;
|
||||
@ -355,7 +355,7 @@ class AnnotationDriver implements Driver
|
||||
$mapping['cascade'] = $manyToOneAnnot->cascade;
|
||||
$mapping['inversedBy'] = $manyToOneAnnot->inversedBy;
|
||||
$mapping['targetEntity'] = $manyToOneAnnot->targetEntity;
|
||||
$mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToOneAnnot->fetch);
|
||||
$mapping['fetch'] = $this->getFetchMode($className, $manyToOneAnnot->fetch);
|
||||
$metadata->mapManyToOne($mapping);
|
||||
} else if ($manyToManyAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\ManyToMany')) {
|
||||
$joinTable = array();
|
||||
@ -395,7 +395,7 @@ class AnnotationDriver implements Driver
|
||||
$mapping['inversedBy'] = $manyToManyAnnot->inversedBy;
|
||||
$mapping['cascade'] = $manyToManyAnnot->cascade;
|
||||
$mapping['indexBy'] = $manyToManyAnnot->indexBy;
|
||||
$mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToManyAnnot->fetch);
|
||||
$mapping['fetch'] = $this->getFetchMode($className, $manyToManyAnnot->fetch);
|
||||
|
||||
if ($orderByAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OrderBy')) {
|
||||
$mapping['orderBy'] = $orderByAnnot->value;
|
||||
@ -446,6 +446,10 @@ class AnnotationDriver implements Driver
|
||||
if (isset($annotations['Doctrine\ORM\Mapping\PostLoad'])) {
|
||||
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::postLoad);
|
||||
}
|
||||
|
||||
if (isset($annotations['Doctrine\ORM\Mapping\PreFlush'])) {
|
||||
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::preFlush);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -536,6 +540,22 @@ class AnnotationDriver implements Driver
|
||||
return $classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to resolve the fetch mode.
|
||||
*
|
||||
* @param string $className The class name
|
||||
* @param string $fetchMode The fetch mode
|
||||
* @return integer The fetch mode as defined in ClassMetadata
|
||||
* @throws MappingException If the fetch mode is not valid
|
||||
*/
|
||||
private function getFetchMode($className, $fetchMode)
|
||||
{
|
||||
if(!defined('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $fetchMode)) {
|
||||
throw MappingException::invalidFetchMode($className, $fetchMode);
|
||||
}
|
||||
|
||||
return constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $fetchMode);
|
||||
}
|
||||
/**
|
||||
* Factory method for the Annotation Driver
|
||||
*
|
||||
|
@ -387,3 +387,9 @@ final class PostRemove implements Annotation {}
|
||||
* @Target("METHOD")
|
||||
*/
|
||||
final class PostLoad implements Annotation {}
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("METHOD")
|
||||
*/
|
||||
final class PreFlush implements Annotation {}
|
||||
|
@ -89,7 +89,7 @@ class XmlDriver extends AbstractFileDriver
|
||||
if (isset($xmlRoot['schema'])) {
|
||||
$metadata->table['schema'] = (string)$xmlRoot['schema'];
|
||||
}*/
|
||||
|
||||
|
||||
if (isset($xmlRoot['inheritance-type'])) {
|
||||
$inheritanceType = (string)$xmlRoot['inheritance-type'];
|
||||
$metadata->setInheritanceType(constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . $inheritanceType));
|
||||
@ -166,9 +166,12 @@ class XmlDriver extends AbstractFileDriver
|
||||
foreach ($xmlRoot->field as $fieldMapping) {
|
||||
$mapping = array(
|
||||
'fieldName' => (string)$fieldMapping['name'],
|
||||
'type' => (string)$fieldMapping['type']
|
||||
);
|
||||
|
||||
if (isset($fieldMapping['type'])) {
|
||||
$mapping['type'] = (string)$fieldMapping['type'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['column'])) {
|
||||
$mapping['columnName'] = (string)$fieldMapping['column'];
|
||||
}
|
||||
@ -219,9 +222,12 @@ class XmlDriver extends AbstractFileDriver
|
||||
|
||||
$mapping = array(
|
||||
'id' => true,
|
||||
'fieldName' => (string)$idElement['name'],
|
||||
'type' => (string)$idElement['type']
|
||||
'fieldName' => (string)$idElement['name']
|
||||
);
|
||||
|
||||
if (isset($fieldMapping['type'])) {
|
||||
$mapping['type'] = (string)$idElement['type'];
|
||||
}
|
||||
|
||||
if (isset($idElement['column'])) {
|
||||
$mapping['columnName'] = (string)$idElement['column'];
|
||||
@ -327,6 +333,8 @@ class XmlDriver extends AbstractFileDriver
|
||||
|
||||
if (isset($oneToManyElement['index-by'])) {
|
||||
$mapping['indexBy'] = (string)$oneToManyElement['index-by'];
|
||||
} else if (isset($oneToManyElement->{'index-by'})) {
|
||||
throw new \InvalidArgumentException("<index-by /> is not a valid tag");
|
||||
}
|
||||
|
||||
$metadata->mapOneToMany($mapping);
|
||||
@ -432,8 +440,10 @@ class XmlDriver extends AbstractFileDriver
|
||||
$mapping['orderBy'] = $orderBy;
|
||||
}
|
||||
|
||||
if (isset($manyToManyElement->{'index-by'})) {
|
||||
$mapping['indexBy'] = (string)$manyToManyElement->{'index-by'};
|
||||
if (isset($manyToManyElement['index-by'])) {
|
||||
$mapping['indexBy'] = (string)$manyToManyElement['index-by'];
|
||||
} else if (isset($manyToManyElement->{'index-by'})) {
|
||||
throw new \InvalidArgumentException("<index-by /> is not a valid tag");
|
||||
}
|
||||
|
||||
$metadata->mapManyToMany($mapping);
|
||||
|
@ -165,15 +165,14 @@ class YamlDriver extends AbstractFileDriver
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($idElement['type'])) {
|
||||
throw MappingException::propertyTypeIsRequired($className, $name);
|
||||
}
|
||||
|
||||
$mapping = array(
|
||||
'id' => true,
|
||||
'fieldName' => $name,
|
||||
'type' => $idElement['type']
|
||||
'fieldName' => $name
|
||||
);
|
||||
|
||||
if (isset($idElement['type'])) {
|
||||
$mapping['type'] = $idElement['type'];
|
||||
}
|
||||
|
||||
if (isset($idElement['column'])) {
|
||||
$mapping['columnName'] = $idElement['column'];
|
||||
@ -201,19 +200,21 @@ class YamlDriver extends AbstractFileDriver
|
||||
// Evaluate fields
|
||||
if (isset($element['fields'])) {
|
||||
foreach ($element['fields'] as $name => $fieldMapping) {
|
||||
if (!isset($fieldMapping['type'])) {
|
||||
throw MappingException::propertyTypeIsRequired($className, $name);
|
||||
}
|
||||
|
||||
$e = explode('(', $fieldMapping['type']);
|
||||
$fieldMapping['type'] = $e[0];
|
||||
if (isset($e[1])) {
|
||||
$fieldMapping['length'] = substr($e[1], 0, strlen($e[1]) - 1);
|
||||
}
|
||||
|
||||
$mapping = array(
|
||||
'fieldName' => $name,
|
||||
'type' => $fieldMapping['type']
|
||||
'fieldName' => $name
|
||||
);
|
||||
|
||||
if (isset($fieldMapping['type'])) {
|
||||
$e = explode('(', $fieldMapping['type']);
|
||||
$fieldMapping['type'] = $e[0];
|
||||
$mapping['type'] = $fieldMapping['type'];
|
||||
|
||||
if (isset($e[1])) {
|
||||
$fieldMapping['length'] = substr($e[1], 0, strlen($e[1]) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['id'])) {
|
||||
$mapping['id'] = true;
|
||||
if (isset($fieldMapping['generator']['strategy'])) {
|
||||
|
@ -298,4 +298,9 @@ class MappingException extends \Doctrine\ORM\ORMException
|
||||
{
|
||||
return new self("Entity '" . $className . "' has no method '" . $methodName . "' to be registered as lifecycle callback.");
|
||||
}
|
||||
}
|
||||
|
||||
public static function invalidFetchMode($className, $annotation)
|
||||
{
|
||||
return new self("Entity '" . $className . "' has a mapping with invalid fetch mode '" . $annotation . "'");
|
||||
}
|
||||
}
|
||||
|
@ -93,21 +93,21 @@ final class PersistentCollection implements Collection
|
||||
|
||||
/**
|
||||
* Whether the collection has already been initialized.
|
||||
*
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private $initialized = true;
|
||||
|
||||
|
||||
/**
|
||||
* The wrapped Collection instance.
|
||||
*
|
||||
*
|
||||
* @var Collection
|
||||
*/
|
||||
private $coll;
|
||||
|
||||
/**
|
||||
* Creates a new persistent collection.
|
||||
*
|
||||
*
|
||||
* @param EntityManager $em The EntityManager the collection will be associated with.
|
||||
* @param ClassMetadata $class The class descriptor of the entity type of this collection.
|
||||
* @param array The collection elements.
|
||||
@ -144,7 +144,7 @@ final class PersistentCollection implements Collection
|
||||
{
|
||||
return $this->owner;
|
||||
}
|
||||
|
||||
|
||||
public function getTypeClass()
|
||||
{
|
||||
return $this->typeClass;
|
||||
@ -154,7 +154,7 @@ final class PersistentCollection implements Collection
|
||||
* INTERNAL:
|
||||
* Adds an element to a collection during hydration. This will automatically
|
||||
* complete bidirectional associations in the case of a one-to-many association.
|
||||
*
|
||||
*
|
||||
* @param mixed $element The element to add.
|
||||
*/
|
||||
public function hydrateAdd($element)
|
||||
@ -172,7 +172,7 @@ final class PersistentCollection implements Collection
|
||||
$this->owner);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Sets a keyed element in the collection during hydration.
|
||||
@ -271,7 +271,7 @@ final class PersistentCollection implements Collection
|
||||
{
|
||||
return $this->association;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Marks this collection as changed/dirty.
|
||||
*/
|
||||
@ -306,17 +306,17 @@ final class PersistentCollection implements Collection
|
||||
{
|
||||
$this->isDirty = $dirty;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the initialized flag of the collection, forcing it into that state.
|
||||
*
|
||||
*
|
||||
* @param boolean $bool
|
||||
*/
|
||||
public function setInitialized($bool)
|
||||
{
|
||||
$this->initialized = $bool;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether this collection has been initialized.
|
||||
*
|
||||
@ -377,7 +377,7 @@ final class PersistentCollection implements Collection
|
||||
$this->em->getUnitOfWork()->getCollectionPersister($this->association)
|
||||
->deleteRows($this, $element);
|
||||
}*/
|
||||
|
||||
|
||||
$this->initialize();
|
||||
$removed = $this->coll->removeElement($element);
|
||||
if ($removed) {
|
||||
@ -410,7 +410,7 @@ final class PersistentCollection implements Collection
|
||||
->getCollectionPersister($this->association)
|
||||
->contains($this, $element);
|
||||
}
|
||||
|
||||
|
||||
$this->initialize();
|
||||
return $this->coll->contains($element);
|
||||
}
|
||||
@ -468,7 +468,7 @@ final class PersistentCollection implements Collection
|
||||
if (!$this->initialized && $this->association['fetch'] == Mapping\ClassMetadataInfo::FETCH_EXTRA_LAZY) {
|
||||
return $this->em->getUnitOfWork()
|
||||
->getCollectionPersister($this->association)
|
||||
->count($this) + $this->coll->count();
|
||||
->count($this) + ($this->isDirty ? $this->coll->count() : 0);
|
||||
}
|
||||
|
||||
$this->initialize();
|
||||
@ -503,7 +503,7 @@ final class PersistentCollection implements Collection
|
||||
$this->initialize();
|
||||
return $this->coll->isEmpty();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@ -530,7 +530,7 @@ final class PersistentCollection implements Collection
|
||||
$this->initialize();
|
||||
return $this->coll->filter($p);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@ -548,7 +548,7 @@ final class PersistentCollection implements Collection
|
||||
$this->initialize();
|
||||
return $this->coll->partition($p);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@ -579,7 +579,7 @@ final class PersistentCollection implements Collection
|
||||
$this->takeSnapshot();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by PHP when this collection is serialized. Ensures that only the
|
||||
* elements are properly serialized.
|
||||
@ -591,7 +591,7 @@ final class PersistentCollection implements Collection
|
||||
{
|
||||
return array('coll', 'initialized');
|
||||
}
|
||||
|
||||
|
||||
/* ArrayAccess implementation */
|
||||
|
||||
/**
|
||||
@ -629,12 +629,12 @@ final class PersistentCollection implements Collection
|
||||
{
|
||||
return $this->remove($offset);
|
||||
}
|
||||
|
||||
|
||||
public function key()
|
||||
{
|
||||
return $this->coll->key();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the element of the collection at the current iterator position.
|
||||
*/
|
||||
@ -642,7 +642,7 @@ final class PersistentCollection implements Collection
|
||||
{
|
||||
return $this->coll->current();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves the internal iterator position to the next element.
|
||||
*/
|
||||
@ -650,7 +650,7 @@ final class PersistentCollection implements Collection
|
||||
{
|
||||
return $this->coll->next();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the wrapped Collection instance.
|
||||
*/
|
||||
@ -672,7 +672,10 @@ final class PersistentCollection implements Collection
|
||||
*/
|
||||
public function slice($offset, $length = null)
|
||||
{
|
||||
if (!$this->initialized && $this->association['fetch'] == Mapping\ClassMetadataInfo::FETCH_EXTRA_LAZY) {
|
||||
if ( ! $this->initialized &&
|
||||
! $this->isDirty &&
|
||||
$this->association['fetch'] == Mapping\ClassMetadataInfo::FETCH_EXTRA_LAZY) {
|
||||
|
||||
return $this->em->getUnitOfWork()
|
||||
->getCollectionPersister($this->association)
|
||||
->slice($this, $offset, $length);
|
||||
|
@ -62,7 +62,7 @@ abstract class AbstractEntityInheritancePersister extends BasicEntityPersister
|
||||
{
|
||||
$columnName = $class->columnNames[$field];
|
||||
$sql = $this->_getSQLTableAlias($class->name, $alias == 'r' ? '' : $alias) . '.' . $class->getQuotedColumnName($field, $this->_platform);
|
||||
$columnAlias = $this->_platform->getSQLResultCasing($columnName . $this->_sqlAliasCounter++);
|
||||
$columnAlias = $this->getSQLColumnAlias($columnName);
|
||||
$this->_rsm->addFieldResult($alias, $columnAlias, $field, $class->name);
|
||||
|
||||
return $sql . ' AS ' . $columnAlias;
|
||||
@ -70,10 +70,9 @@ abstract class AbstractEntityInheritancePersister extends BasicEntityPersister
|
||||
|
||||
protected function getSelectJoinColumnSQL($tableAlias, $joinColumnName, $className)
|
||||
{
|
||||
$columnAlias = $joinColumnName . $this->_sqlAliasCounter++;
|
||||
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
|
||||
$this->_rsm->addMetaResult('r', $resultColumnName, $joinColumnName);
|
||||
$columnAlias = $this->getSQLColumnAlias($joinColumnName);
|
||||
$this->_rsm->addMetaResult('r', $columnAlias, $joinColumnName);
|
||||
|
||||
return $tableAlias . '.' . $joinColumnName . ' AS ' . $columnAlias;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1001,27 +1001,26 @@ class BasicEntityPersister
|
||||
$columnList .= $assoc2ColumnSQL;
|
||||
}
|
||||
}
|
||||
|
||||
$this->_selectJoinSql .= ' LEFT JOIN'; // TODO: Inner join when all join columns are NOT nullable.
|
||||
$first = true;
|
||||
|
||||
if ($assoc['isOwningSide']) {
|
||||
$this->_selectJoinSql .= ' ' . $this->getJoinSQLForJoinColumns($assoc['joinColumns']);
|
||||
$this->_selectJoinSql .= ' ' . $eagerEntity->getQuotedTableName($this->_platform) . ' ' . $this->_getSQLTableAlias($eagerEntity->name, $assocAlias) .' ON ';
|
||||
|
||||
foreach ($assoc['sourceToTargetKeyColumns'] AS $sourceCol => $targetCol) {
|
||||
if ( ! $first) {
|
||||
$this->_selectJoinSql .= ' AND ';
|
||||
}
|
||||
|
||||
$this->_selectJoinSql .= $this->_getSQLTableAlias($assoc['sourceEntity']) . '.' . $sourceCol . ' = '
|
||||
. $this->_getSQLTableAlias($assoc['targetEntity'], $assocAlias) . '.' . $targetCol . ' ';
|
||||
$this->_selectJoinSql .= $this->_getSQLTableAlias($assoc['sourceEntity']) . '.' . $sourceCol . ' = '
|
||||
. $this->_getSQLTableAlias($assoc['targetEntity'], $assocAlias) . '.' . $targetCol;
|
||||
$first = false;
|
||||
}
|
||||
} else {
|
||||
$eagerEntity = $this->_em->getClassMetadata($assoc['targetEntity']);
|
||||
$owningAssoc = $eagerEntity->getAssociationMapping($assoc['mappedBy']);
|
||||
|
||||
$this->_selectJoinSql .= ' ' . $eagerEntity->getQuotedTableName($this->_platform) . ' '
|
||||
$this->_selectJoinSql .= ' LEFT JOIN';
|
||||
$this->_selectJoinSql .= ' ' . $eagerEntity->getQuotedTableName($this->_platform) . ' '
|
||||
. $this->_getSQLTableAlias($eagerEntity->name, $assocAlias) . ' ON ';
|
||||
|
||||
foreach ($owningAssoc['sourceToTargetKeyColumns'] AS $sourceCol => $targetCol) {
|
||||
@ -1030,7 +1029,7 @@ class BasicEntityPersister
|
||||
}
|
||||
|
||||
$this->_selectJoinSql .= $this->_getSQLTableAlias($owningAssoc['sourceEntity'], $assocAlias) . '.' . $sourceCol . ' = '
|
||||
. $this->_getSQLTableAlias($owningAssoc['targetEntity']) . '.' . $targetCol . ' ';
|
||||
. $this->_getSQLTableAlias($owningAssoc['targetEntity']) . '.' . $targetCol;
|
||||
$first = false;
|
||||
}
|
||||
}
|
||||
@ -1060,9 +1059,8 @@ class BasicEntityPersister
|
||||
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
|
||||
if ($columnList) $columnList .= ', ';
|
||||
|
||||
$columnAlias = $srcColumn . $this->_sqlAliasCounter++;
|
||||
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
|
||||
$columnList .= $this->_getSQLTableAlias($class->name, ($alias == 'r' ? '' : $alias) )
|
||||
$resultColumnName = $this->getSQLColumnAlias($srcColumn);
|
||||
$columnList .= $this->_getSQLTableAlias($class->name, ($alias == 'r' ? '' : $alias) )
|
||||
. '.' . $srcColumn . ' AS ' . $resultColumnName;
|
||||
$this->_rsm->addMetaResult($alias, $resultColumnName, $srcColumn, isset($assoc['id']) && $assoc['id'] === true);
|
||||
}
|
||||
@ -1180,10 +1178,9 @@ class BasicEntityPersister
|
||||
*/
|
||||
protected function _getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r')
|
||||
{
|
||||
$columnName = $class->columnNames[$field];
|
||||
$sql = $this->_getSQLTableAlias($class->name, $alias == 'r' ? '' : $alias)
|
||||
$sql = $this->_getSQLTableAlias($class->name, $alias == 'r' ? '' : $alias)
|
||||
. '.' . $class->getQuotedColumnName($field, $this->_platform);
|
||||
$columnAlias = $this->_platform->getSQLResultCasing($columnName . $this->_sqlAliasCounter++);
|
||||
$columnAlias = $this->getSQLColumnAlias($class->columnNames[$field]);
|
||||
|
||||
$this->_rsm->addFieldResult($alias, $columnAlias, $field);
|
||||
|
||||
@ -1500,4 +1497,37 @@ class BasicEntityPersister
|
||||
|
||||
return (bool) $this->_conn->fetchColumn($sql, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the appropriate join SQL for the given join column.
|
||||
*
|
||||
* @param array $joinColumns The join columns definition of an association.
|
||||
* @return string LEFT JOIN if one of the columns is nullable, INNER JOIN otherwise.
|
||||
*/
|
||||
protected function getJoinSQLForJoinColumns($joinColumns)
|
||||
{
|
||||
// if one of the join columns is nullable, return left join
|
||||
foreach($joinColumns as $joinColumn) {
|
||||
if(isset($joinColumn['nullable']) && $joinColumn['nullable']){
|
||||
return 'LEFT JOIN';
|
||||
}
|
||||
}
|
||||
|
||||
return 'INNER JOIN';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an SQL column alias for a column name.
|
||||
*
|
||||
* @param string $columnName
|
||||
* @return string
|
||||
*/
|
||||
public function getSQLColumnAlias($columnName)
|
||||
{
|
||||
// Trim the column alias to the maximum identifier length of the platform.
|
||||
// If the alias is to long, characters are cut off from the beginning.
|
||||
return $this->_platform->getSQLResultCasing(
|
||||
substr($columnName . $this->_sqlAliasCounter++, -$this->_platform->getMaxIdentifierLength())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -165,11 +165,13 @@ class ProxyFactory
|
||||
{
|
||||
$methods = '';
|
||||
|
||||
$methodNames = array();
|
||||
foreach ($class->reflClass->getMethods() as $method) {
|
||||
/* @var $method ReflectionMethod */
|
||||
if ($method->isConstructor() || in_array(strtolower($method->getName()), array("__sleep", "__clone"))) {
|
||||
if ($method->isConstructor() || in_array(strtolower($method->getName()), array("__sleep", "__clone")) || isset($methodNames[$method->getName()])) {
|
||||
continue;
|
||||
}
|
||||
$methodNames[$method->getName()] = true;
|
||||
|
||||
if ($method->isPublic() && ! $method->isFinal() && ! $method->isStatic()) {
|
||||
$methods .= "\n" . ' public function ';
|
||||
@ -210,8 +212,12 @@ class ProxyFactory
|
||||
$methods .= $parameterString . ')';
|
||||
$methods .= "\n" . ' {' . "\n";
|
||||
if ($this->isShortIdentifierGetter($method, $class)) {
|
||||
$identifier = lcfirst(substr($method->getName(), 3));
|
||||
|
||||
$cast = in_array($class->fieldMappings[$identifier]['type'], array('integer', 'smallint')) ? '(int) ' : '';
|
||||
|
||||
$methods .= ' if ($this->__isInitialized__ === false) {' . "\n";
|
||||
$methods .= ' return $this->_identifier["' . lcfirst(substr($method->getName(), 3)) . '"];' . "\n";
|
||||
$methods .= ' return ' . $cast . '$this->_identifier["' . $identifier . '"];' . "\n";
|
||||
$methods .= ' }' . "\n";
|
||||
}
|
||||
$methods .= ' $this->__load();' . "\n";
|
||||
@ -230,13 +236,14 @@ class ProxyFactory
|
||||
*/
|
||||
private function isShortIdentifierGetter($method, $class)
|
||||
{
|
||||
$identifier = lcfirst(substr($method->getName(), 3));
|
||||
$identifier = lcfirst(substr($method->getName(), 3));
|
||||
return (
|
||||
$method->getNumberOfParameters() == 0 &&
|
||||
substr($method->getName(), 0, 3) == "get" &&
|
||||
in_array($identifier, $class->identifier, true) &&
|
||||
$class->hasField($identifier) &&
|
||||
(($method->getEndLine() - $method->getStartLine()) <= 4)
|
||||
&& in_array($class->fieldMappings[$identifier]['type'], array('integer', 'bigint', 'smallint', 'string'))
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -526,7 +526,7 @@ final class Query extends AbstractQuery
|
||||
*
|
||||
* @param array $params The query parameters.
|
||||
* @param integer $hydrationMode The hydration mode to use.
|
||||
* @return IterableResult
|
||||
* @return \Doctrine\ORM\Internal\Hydration\IterableResult
|
||||
*/
|
||||
public function iterate(array $params = array(), $hydrationMode = self::HYDRATE_OBJECT)
|
||||
{
|
||||
|
@ -39,30 +39,30 @@ class Composite extends Base
|
||||
if ($this->count() === 1) {
|
||||
return (string) $this->_parts[0];
|
||||
}
|
||||
|
||||
|
||||
$components = array();
|
||||
|
||||
|
||||
foreach ($this->_parts as $part) {
|
||||
$components[] = $this->processQueryPart($part);
|
||||
}
|
||||
|
||||
|
||||
return implode($this->_separator, $components);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private function processQueryPart($part)
|
||||
{
|
||||
$queryPart = (string) $part;
|
||||
|
||||
|
||||
if (is_object($part) && $part instanceof self && $part->count() > 1) {
|
||||
return $this->_preSeparator . $queryPart . $this->_postSeparator;
|
||||
}
|
||||
|
||||
|
||||
// Fixes DDC-1237: User may have added a where item containing nested expression (with "OR" or "AND")
|
||||
if (mb_stripos($queryPart, ' OR ') !== false || mb_stripos($queryPart, ' AND ') !== false) {
|
||||
if (stripos($queryPart, ' OR ') !== false || stripos($queryPart, ' AND ') !== false) {
|
||||
return $this->_preSeparator . $queryPart . $this->_postSeparator;
|
||||
}
|
||||
|
||||
|
||||
return $queryPart;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -47,6 +47,11 @@ class QueryException extends \Doctrine\ORM\ORMException
|
||||
return new self('[Semantical Error] ' . $message);
|
||||
}
|
||||
|
||||
public static function invalidLockMode()
|
||||
{
|
||||
return new self('Invalid lock mode hint provided.');
|
||||
}
|
||||
|
||||
public static function invalidParameterType($expected, $received)
|
||||
{
|
||||
return new self('Invalid parameter type, ' . $received . ' given, but ' . $expected . ' expected.');
|
||||
|
@ -26,7 +26,7 @@ namespace Doctrine\ORM\Query;
|
||||
* The properties of this class are only public for fast internal READ access and to (drastically)
|
||||
* reduce the size of serialized instances for more effective caching due to better (un-)serialization
|
||||
* performance.
|
||||
*
|
||||
*
|
||||
* <b>Users should use the public methods.</b>
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
@ -36,87 +36,79 @@ namespace Doctrine\ORM\Query;
|
||||
class ResultSetMapping
|
||||
{
|
||||
/**
|
||||
* Whether the result is mixed (contains scalar values together with field values).
|
||||
*
|
||||
* @ignore
|
||||
* @var boolean
|
||||
* @var boolean Whether the result is mixed (contains scalar values together with field values).
|
||||
*/
|
||||
public $isMixed = false;
|
||||
|
||||
/**
|
||||
* Maps alias names to class names.
|
||||
*
|
||||
* @ignore
|
||||
* @var array
|
||||
* @var array Maps alias names to class names.
|
||||
*/
|
||||
public $aliasMap = array();
|
||||
|
||||
/**
|
||||
* Maps alias names to related association field names.
|
||||
*
|
||||
* @ignore
|
||||
* @var array
|
||||
* @var array Maps alias names to related association field names.
|
||||
*/
|
||||
public $relationMap = array();
|
||||
|
||||
/**
|
||||
* Maps alias names to parent alias names.
|
||||
*
|
||||
* @ignore
|
||||
* @var array
|
||||
* @var array Maps alias names to parent alias names.
|
||||
*/
|
||||
public $parentAliasMap = array();
|
||||
|
||||
/**
|
||||
* Maps column names in the result set to field names for each class.
|
||||
*
|
||||
* @ignore
|
||||
* @var array
|
||||
* @var array Maps column names in the result set to field names for each class.
|
||||
*/
|
||||
public $fieldMappings = array();
|
||||
|
||||
/**
|
||||
* Maps column names in the result set to the alias/field name to use in the mapped result.
|
||||
*
|
||||
* @ignore
|
||||
* @var array
|
||||
* @var array Maps column names in the result set to the alias/field name to use in the mapped result.
|
||||
*/
|
||||
public $scalarMappings = array();
|
||||
|
||||
/**
|
||||
* Maps column names of meta columns (foreign keys, discriminator columns, ...) to field names.
|
||||
*
|
||||
* @ignore
|
||||
* @var array
|
||||
* @var array Maps entities in the result set to the alias name to use in the mapped result.
|
||||
*/
|
||||
public $entityMappings = array();
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
* @var array Maps column names of meta columns (foreign keys, discriminator columns, ...) to field names.
|
||||
*/
|
||||
public $metaMappings = array();
|
||||
|
||||
/**
|
||||
* Maps column names in the result set to the alias they belong to.
|
||||
*
|
||||
* @ignore
|
||||
* @var array
|
||||
* @var array Maps column names in the result set to the alias they belong to.
|
||||
*/
|
||||
public $columnOwnerMap = array();
|
||||
|
||||
/**
|
||||
* List of columns in the result set that are used as discriminator columns.
|
||||
*
|
||||
* @ignore
|
||||
* @var array
|
||||
* @var array List of columns in the result set that are used as discriminator columns.
|
||||
*/
|
||||
public $discriminatorColumns = array();
|
||||
|
||||
/**
|
||||
* Maps alias names to field names that should be used for indexing.
|
||||
*
|
||||
* @ignore
|
||||
* @var array
|
||||
* @var array Maps alias names to field names that should be used for indexing.
|
||||
*/
|
||||
public $indexByMap = array();
|
||||
|
||||
/**
|
||||
* Map from column names to class names that declare the field the column is mapped to.
|
||||
*
|
||||
* @ignore
|
||||
* @var array
|
||||
* @var array Map from column names to class names that declare the field the column is mapped to.
|
||||
*/
|
||||
public $declaringClasses = array();
|
||||
|
||||
|
||||
/**
|
||||
* This is necessary to hydrate derivate foreign keys correctly.
|
||||
*
|
||||
* @var array
|
||||
* @var array This is necessary to hydrate derivate foreign keys correctly.
|
||||
*/
|
||||
public $isIdentifierColumn = array();
|
||||
|
||||
@ -126,11 +118,15 @@ class ResultSetMapping
|
||||
* @param string $class The class name of the entity.
|
||||
* @param string $alias The alias for the class. The alias must be unique among all entity
|
||||
* results or joined entity results within this ResultSetMapping.
|
||||
* @param string $resultAlias The result alias with which the entity result should be
|
||||
* placed in the result structure.
|
||||
*
|
||||
* @todo Rename: addRootEntity
|
||||
*/
|
||||
public function addEntityResult($class, $alias)
|
||||
public function addEntityResult($class, $alias, $resultAlias = null)
|
||||
{
|
||||
$this->aliasMap[$alias] = $class;
|
||||
$this->entityMappings[$alias] = $resultAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -141,6 +137,7 @@ class ResultSetMapping
|
||||
* @param string $alias The alias of the entity result or joined entity result the discriminator
|
||||
* column should be used for.
|
||||
* @param string $discrColumn The name of the discriminator column in the SQL result set.
|
||||
*
|
||||
* @todo Rename: addDiscriminatorColumn
|
||||
*/
|
||||
public function setDiscriminatorColumn($alias, $discrColumn)
|
||||
@ -157,7 +154,51 @@ class ResultSetMapping
|
||||
*/
|
||||
public function addIndexBy($alias, $fieldName)
|
||||
{
|
||||
$this->indexByMap[$alias] = $fieldName;
|
||||
$found = false;
|
||||
|
||||
foreach ($this->fieldMappings AS $columnName => $columnFieldName) {
|
||||
if ( ! ($columnFieldName === $fieldName && $this->columnOwnerMap[$columnName] === $alias)) continue;
|
||||
|
||||
$this->addIndexByColumn($alias, $columnName);
|
||||
$found = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* TODO: check if this exception can be put back, for now it's gone because of assumptions made by some ORM internals
|
||||
if ( ! $found) {
|
||||
$message = sprintf(
|
||||
'Cannot add index by for DQL alias %s and field %s without calling addFieldResult() for them before.',
|
||||
$alias,
|
||||
$fieldName
|
||||
);
|
||||
|
||||
throw new \LogicException($message);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to index by a scalar result column name
|
||||
*
|
||||
* @param $resultColumnName
|
||||
* @return void
|
||||
*/
|
||||
public function addIndexByScalar($resultColumnName)
|
||||
{
|
||||
$this->indexByMap['scalars'] = $resultColumnName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a column to use for indexing an entity or joined entity result by the given alias name.
|
||||
*
|
||||
* @param $alias
|
||||
* @param $resultColumnName
|
||||
* @return void
|
||||
*/
|
||||
public function addIndexByColumn($alias, $resultColumnName)
|
||||
{
|
||||
$this->indexByMap[$alias] = $resultColumnName;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -207,6 +248,7 @@ class ResultSetMapping
|
||||
$this->columnOwnerMap[$columnName] = $alias;
|
||||
// field name => class name of declaring class
|
||||
$this->declaringClasses[$columnName] = $declaringClass ?: $this->aliasMap[$alias];
|
||||
|
||||
if ( ! $this->isMixed && $this->scalarMappings) {
|
||||
$this->isMixed = true;
|
||||
}
|
||||
@ -223,11 +265,11 @@ class ResultSetMapping
|
||||
*/
|
||||
public function addJoinedEntityResult($class, $alias, $parentAlias, $relation)
|
||||
{
|
||||
$this->aliasMap[$alias] = $class;
|
||||
$this->aliasMap[$alias] = $class;
|
||||
$this->parentAliasMap[$alias] = $parentAlias;
|
||||
$this->relationMap[$alias] = $relation;
|
||||
$this->relationMap[$alias] = $relation;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a scalar result mapping.
|
||||
*
|
||||
@ -238,6 +280,7 @@ class ResultSetMapping
|
||||
public function addScalarResult($columnName, $alias)
|
||||
{
|
||||
$this->scalarMappings[$columnName] = $alias;
|
||||
|
||||
if ( ! $this->isMixed && $this->fieldMappings) {
|
||||
$this->isMixed = true;
|
||||
}
|
||||
@ -245,7 +288,7 @@ class ResultSetMapping
|
||||
|
||||
/**
|
||||
* Checks whether a column with a given name is mapped as a scalar result.
|
||||
*
|
||||
*
|
||||
* @param string $columName The name of the column in the SQL result set.
|
||||
* @return boolean
|
||||
* @todo Rename: isScalar
|
||||
@ -384,10 +427,10 @@ class ResultSetMapping
|
||||
{
|
||||
return $this->isMixed;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a meta column (foreign key or discriminator column) to the result set.
|
||||
*
|
||||
*
|
||||
* @param string $alias
|
||||
* @param string $columnName
|
||||
* @param string $fieldName
|
||||
@ -397,8 +440,9 @@ class ResultSetMapping
|
||||
{
|
||||
$this->metaMappings[$columnName] = $fieldName;
|
||||
$this->columnOwnerMap[$columnName] = $alias;
|
||||
|
||||
if ($isIdentifierColumn) {
|
||||
$this->isIdentifierColumn[$alias][$columnName] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,20 +86,22 @@ class ResultSetMappingBuilder extends ResultSetMapping
|
||||
if (isset($renamedColumns[$columnName])) {
|
||||
$columnName = $renamedColumns[$columnName];
|
||||
}
|
||||
$columnName = $platform->getSQLResultCasing($columnName);
|
||||
if (isset($this->fieldMappings[$columnName])) {
|
||||
throw new \InvalidArgumentException("The column '$columnName' conflicts with another column in the mapper.");
|
||||
}
|
||||
$this->addFieldResult($alias, $platform->getSQLResultCasing($columnName), $propertyName);
|
||||
$this->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'];
|
||||
$renamedColumnName = isset($renamedColumns[$columnName]) ? $renamedColumns[$columnName] : $columnName;
|
||||
$renamedColumnName = $platform->getSQLResultCasing($renamedColumnName);
|
||||
if (isset($this->metaMappings[$renamedColumnName])) {
|
||||
throw new \InvalidArgumentException("The column '$renamedColumnName' conflicts with another column in the mapper.");
|
||||
}
|
||||
$this->addMetaResult($alias, $platform->getSQLResultCasing($renamedColumnName), $platform->getSQLResultCasing($columnName));
|
||||
$this->addMetaResult($alias, $renamedColumnName, $columnName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -117,7 +117,7 @@ public function <methodName>()
|
||||
* @param <variableType>$<variableName>
|
||||
* @return <entity>
|
||||
*/
|
||||
public function <methodName>(<methodTypeHint>$<variableName>)
|
||||
public function <methodName>(<methodTypeHint>$<variableName><variableDefault>)
|
||||
{
|
||||
<spaces>$this-><fieldName> = $<variableName>;
|
||||
<spaces>return $this;
|
||||
@ -406,7 +406,7 @@ public function <methodName>()
|
||||
}
|
||||
|
||||
if ($collections) {
|
||||
return $this->_prefixCodeWithSpaces(str_replace("<collections>", implode("\n", $collections), self::$_constructorMethodTemplate));
|
||||
return $this->_prefixCodeWithSpaces(str_replace("<collections>", implode("\n".$this->_spaces, $collections), self::$_constructorMethodTemplate));
|
||||
}
|
||||
|
||||
return '';
|
||||
@ -634,7 +634,8 @@ public function <methodName>()
|
||||
|
||||
foreach ($metadata->associationMappings as $associationMapping) {
|
||||
if ($associationMapping['type'] & ClassMetadataInfo::TO_ONE) {
|
||||
if ($code = $this->_generateEntityStubMethod($metadata, 'set', $associationMapping['fieldName'], $associationMapping['targetEntity'])) {
|
||||
$nullable = $this->_isAssociationIsNullable($associationMapping) ? 'null' : null;
|
||||
if ($code = $this->_generateEntityStubMethod($metadata, 'set', $associationMapping['fieldName'], $associationMapping['targetEntity'], $nullable)) {
|
||||
$methods[] = $code;
|
||||
}
|
||||
if ($code = $this->_generateEntityStubMethod($metadata, 'get', $associationMapping['fieldName'], $associationMapping['targetEntity'])) {
|
||||
@ -653,6 +654,22 @@ public function <methodName>()
|
||||
return implode("\n\n", $methods);
|
||||
}
|
||||
|
||||
private function _isAssociationIsNullable($associationMapping)
|
||||
{
|
||||
if (isset($associationMapping['joinColumns'])) {
|
||||
$joinColumns = $associationMapping['joinColumns'];
|
||||
} else {
|
||||
//@todo thereis no way to retreive targetEntity metadata
|
||||
$joinColumns = array();
|
||||
}
|
||||
foreach ($joinColumns as $joinColumn) {
|
||||
if(isset($joinColumn['nullable']) && !$joinColumn['nullable']) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function _generateEntityLifecycleCallbackMethods(ClassMetadataInfo $metadata)
|
||||
{
|
||||
if (isset($metadata->lifecycleCallbacks) && $metadata->lifecycleCallbacks) {
|
||||
@ -707,7 +724,7 @@ public function <methodName>()
|
||||
return implode("\n", $lines);
|
||||
}
|
||||
|
||||
private function _generateEntityStubMethod(ClassMetadataInfo $metadata, $type, $fieldName, $typeHint = null)
|
||||
private function _generateEntityStubMethod(ClassMetadataInfo $metadata, $type, $fieldName, $typeHint = null, $defaultValue = null)
|
||||
{
|
||||
if ($type == "add") {
|
||||
$addMethod = explode("\\", $typeHint);
|
||||
@ -737,6 +754,7 @@ public function <methodName>()
|
||||
'<variableName>' => Inflector::camelize($fieldName),
|
||||
'<methodName>' => $methodName,
|
||||
'<fieldName>' => $fieldName,
|
||||
'<variableDefault>' => ($defaultValue !== null ) ? ('='.$defaultValue) : '',
|
||||
'<entity>' => $this->_getClassName($metadata)
|
||||
);
|
||||
|
||||
@ -805,7 +823,12 @@ public function <methodName>()
|
||||
{
|
||||
$lines = array();
|
||||
$lines[] = $this->_spaces . '/**';
|
||||
$lines[] = $this->_spaces . ' * @var ' . $associationMapping['targetEntity'];
|
||||
|
||||
if ($associationMapping['type'] & ClassMetadataInfo::TO_MANY) {
|
||||
$lines[] = $this->_spaces . ' * @var \Doctrine\Common\Collections\ArrayCollection';
|
||||
} else {
|
||||
$lines[] = $this->_spaces . ' * @var ' . $associationMapping['targetEntity'];
|
||||
}
|
||||
|
||||
if ($this->_generateAnnotations) {
|
||||
$lines[] = $this->_spaces . ' *';
|
||||
|
@ -67,7 +67,9 @@ class SchemaTool
|
||||
/**
|
||||
* Creates the database schema for the given array of ClassMetadata instances.
|
||||
*
|
||||
* @throws ToolsException
|
||||
* @param array $classes
|
||||
* @return void
|
||||
*/
|
||||
public function createSchema(array $classes)
|
||||
{
|
||||
@ -75,7 +77,11 @@ class SchemaTool
|
||||
$conn = $this->_em->getConnection();
|
||||
|
||||
foreach ($createSchemaSql as $sql) {
|
||||
$conn->executeQuery($sql);
|
||||
try {
|
||||
$conn->executeQuery($sql);
|
||||
} catch(\Exception $e) {
|
||||
throw ToolsException::schemaToolFailure($sql, $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,7 +100,7 @@ class SchemaTool
|
||||
|
||||
/**
|
||||
* Some instances of ClassMetadata don't need to be processed in the SchemaTool context. This method detects them.
|
||||
*
|
||||
*
|
||||
* @param ClassMetadata $class
|
||||
* @param array $processedClasses
|
||||
* @return bool
|
||||
@ -139,7 +145,7 @@ class SchemaTool
|
||||
$this->_gatherRelationsSql($class, $table, $schema);
|
||||
|
||||
// Add the discriminator column
|
||||
$discrColumnDef = $this->_getDiscriminatorColumnDefinition($class, $table);
|
||||
$this->addDiscriminatorColumnDefinition($class, $table);
|
||||
|
||||
// Aggregate all the information from all classes in the hierarchy
|
||||
foreach ($class->parentClasses as $parentClassName) {
|
||||
@ -171,7 +177,7 @@ class SchemaTool
|
||||
|
||||
// Add the discriminator column only to the root table
|
||||
if ($class->name == $class->rootEntityName) {
|
||||
$discrColumnDef = $this->_getDiscriminatorColumnDefinition($class, $table);
|
||||
$this->addDiscriminatorColumnDefinition($class, $table);
|
||||
} else {
|
||||
// Add an ID FK column to child tables
|
||||
/* @var Doctrine\ORM\Mapping\ClassMetadata $class */
|
||||
@ -261,7 +267,7 @@ class SchemaTool
|
||||
* @return array The portable column definition of the discriminator column as required by
|
||||
* the DBAL.
|
||||
*/
|
||||
private function _getDiscriminatorColumnDefinition($class, $table)
|
||||
private function addDiscriminatorColumnDefinition($class, $table)
|
||||
{
|
||||
$discrColumn = $class->discriminatorColumn;
|
||||
|
||||
@ -551,7 +557,7 @@ class SchemaTool
|
||||
try {
|
||||
$conn->executeQuery($sql);
|
||||
} catch(\Exception $e) {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -589,7 +595,7 @@ class SchemaTool
|
||||
|
||||
/**
|
||||
* Get SQL to drop the tables defined by the passed classes.
|
||||
*
|
||||
*
|
||||
* @param array $classes
|
||||
* @return array
|
||||
*/
|
||||
@ -615,7 +621,7 @@ class SchemaTool
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($this->_platform->supportsSequences()) {
|
||||
foreach ($schema->getSequences() AS $sequence) {
|
||||
$visitor->acceptSequence($sequence);
|
||||
@ -659,7 +665,7 @@ class SchemaTool
|
||||
/**
|
||||
* Gets the sequence of SQL statements that need to be performed in order
|
||||
* to bring the given class mappings in-synch with the relational schema.
|
||||
* If $saveMode is set to true the command is executed in the Database,
|
||||
* If $saveMode is set to true the command is executed in the Database,
|
||||
* else SQL is returned.
|
||||
*
|
||||
* @param array $classes The classes to consider.
|
||||
|
@ -50,7 +50,7 @@ class SchemaValidator
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the internal consistency of mapping files.
|
||||
* Checks the internal consistency of all mapping files.
|
||||
*
|
||||
* There are several checks that can't be done at runtime or are too expensive, which can be verified
|
||||
* with this command. For example:
|
||||
@ -69,150 +69,7 @@ class SchemaValidator
|
||||
$classes = $cmf->getAllMetadata();
|
||||
|
||||
foreach ($classes AS $class) {
|
||||
$ce = array();
|
||||
/* @var $class ClassMetadata */
|
||||
foreach ($class->associationMappings AS $fieldName => $assoc) {
|
||||
if (!$cmf->hasMetadataFor($assoc['targetEntity'])) {
|
||||
$ce[] = "The target entity '" . $assoc['targetEntity'] . "' specified on " . $class->name . '#' . $fieldName . ' is unknown.';
|
||||
}
|
||||
|
||||
if ($assoc['mappedBy'] && $assoc['inversedBy']) {
|
||||
$ce[] = "The association " . $class . "#" . $fieldName . " cannot be defined as both inverse and owning.";
|
||||
}
|
||||
|
||||
$targetMetadata = $cmf->getMetadataFor($assoc['targetEntity']);
|
||||
|
||||
/* @var $assoc AssociationMapping */
|
||||
if ($assoc['mappedBy']) {
|
||||
if ($targetMetadata->hasField($assoc['mappedBy'])) {
|
||||
$ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the owning side ".
|
||||
"field " . $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " which is not defined as association.";
|
||||
}
|
||||
if (!$targetMetadata->hasAssociation($assoc['mappedBy'])) {
|
||||
$ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the owning side ".
|
||||
"field " . $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " which does not exist.";
|
||||
} else if ($targetMetadata->associationMappings[$assoc['mappedBy']]['inversedBy'] == null) {
|
||||
$ce[] = "The field " . $class->name . "#" . $fieldName . " is on the inverse side of a ".
|
||||
"bi-directional relationship, but the specified mappedBy association on the target-entity ".
|
||||
$assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " does not contain the required ".
|
||||
"'inversedBy' attribute.";
|
||||
} else if ($targetMetadata->associationMappings[$assoc['mappedBy']]['inversedBy'] != $fieldName) {
|
||||
$ce[] = "The mappings " . $class->name . "#" . $fieldName . " and " .
|
||||
$assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " are ".
|
||||
"incosistent with each other.";
|
||||
}
|
||||
}
|
||||
|
||||
if ($assoc['inversedBy']) {
|
||||
if ($targetMetadata->hasField($assoc['inversedBy'])) {
|
||||
$ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the inverse side ".
|
||||
"field " . $assoc['targetEntity'] . "#" . $assoc['inversedBy'] . " which is not defined as association.";
|
||||
}
|
||||
if (!$targetMetadata->hasAssociation($assoc['inversedBy'])) {
|
||||
$ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the inverse side ".
|
||||
"field " . $assoc['targetEntity'] . "#" . $assoc['inversedBy'] . " which does not exist.";
|
||||
} else if ($targetMetadata->associationMappings[$assoc['inversedBy']]['mappedBy'] == null) {
|
||||
$ce[] = "The field " . $class->name . "#" . $fieldName . " is on the owning side of a ".
|
||||
"bi-directional relationship, but the specified mappedBy association on the target-entity ".
|
||||
$assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " does not contain the required ".
|
||||
"'inversedBy' attribute.";
|
||||
} else if ($targetMetadata->associationMappings[$assoc['inversedBy']]['mappedBy'] != $fieldName) {
|
||||
$ce[] = "The mappings " . $class->name . "#" . $fieldName . " and " .
|
||||
$assoc['targetEntity'] . "#" . $assoc['inversedBy'] . " are ".
|
||||
"incosistent with each other.";
|
||||
}
|
||||
}
|
||||
|
||||
if ($assoc['isOwningSide']) {
|
||||
if ($assoc['type'] == ClassMetadataInfo::MANY_TO_MANY) {
|
||||
foreach ($assoc['joinTable']['joinColumns'] AS $joinColumn) {
|
||||
if (!isset($class->fieldNames[$joinColumn['referencedColumnName']])) {
|
||||
$ce[] = "The referenced column name '" . $joinColumn['referencedColumnName'] . "' does not " .
|
||||
"have a corresponding field with this column name on the class '" . $class->name . "'.";
|
||||
break;
|
||||
}
|
||||
|
||||
$fieldName = $class->fieldNames[$joinColumn['referencedColumnName']];
|
||||
if (!in_array($fieldName, $class->identifier)) {
|
||||
$ce[] = "The referenced column name '" . $joinColumn['referencedColumnName'] . "' " .
|
||||
"has to be a primary key column.";
|
||||
}
|
||||
}
|
||||
foreach ($assoc['joinTable']['inverseJoinColumns'] AS $inverseJoinColumn) {
|
||||
$targetClass = $cmf->getMetadataFor($assoc['targetEntity']);
|
||||
if (!isset($targetClass->fieldNames[$inverseJoinColumn['referencedColumnName']])) {
|
||||
$ce[] = "The inverse referenced column name '" . $inverseJoinColumn['referencedColumnName'] . "' does not " .
|
||||
"have a corresponding field with this column name on the class '" . $targetClass->name . "'.";
|
||||
break;
|
||||
}
|
||||
|
||||
$fieldName = $targetClass->fieldNames[$inverseJoinColumn['referencedColumnName']];
|
||||
if (!in_array($fieldName, $targetClass->identifier)) {
|
||||
$ce[] = "The referenced column name '" . $inverseJoinColumn['referencedColumnName'] . "' " .
|
||||
"has to be a primary key column.";
|
||||
}
|
||||
}
|
||||
|
||||
if (count($targetClass->identifier) != count($assoc['joinTable']['inverseJoinColumns'])) {
|
||||
$ce[] = "The inverse join columns of the many-to-many table '" . $assoc['joinTable']['name'] . "' " .
|
||||
"have to match to ALL identifier columns of the target entity '". $targetClass->name . "'";
|
||||
}
|
||||
|
||||
if (count($class->identifier) != count($assoc['joinTable']['joinColumns'])) {
|
||||
$ce[] = "The join columns of the many-to-many table '" . $assoc['joinTable']['name'] . "' " .
|
||||
"have to match to ALL identifier columns of the source entity '". $class->name . "'";
|
||||
}
|
||||
|
||||
} else if ($assoc['type'] & ClassMetadataInfo::TO_ONE) {
|
||||
foreach ($assoc['joinColumns'] AS $joinColumn) {
|
||||
$targetClass = $cmf->getMetadataFor($assoc['targetEntity']);
|
||||
if (!isset($targetClass->fieldNames[$joinColumn['referencedColumnName']])) {
|
||||
$ce[] = "The referenced column name '" . $joinColumn['referencedColumnName'] . "' does not " .
|
||||
"have a corresponding field with this column name on the class '" . $targetClass->name . "'.";
|
||||
break;
|
||||
}
|
||||
|
||||
$fieldName = $targetClass->fieldNames[$joinColumn['referencedColumnName']];
|
||||
if (!in_array($fieldName, $targetClass->identifier)) {
|
||||
$ce[] = "The referenced column name '" . $joinColumn['referencedColumnName'] . "' " .
|
||||
"has to be a primary key column.";
|
||||
}
|
||||
}
|
||||
|
||||
if (count($class->identifier) != count($assoc['joinColumns'])) {
|
||||
$ce[] = "The join columns of the association '" . $assoc['fieldName'] . "' " .
|
||||
"have to match to ALL identifier columns of the source entity '". $class->name . "'";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($assoc['orderBy']) && $assoc['orderBy'] !== null) {
|
||||
$targetClass = $cmf->getMetadataFor($assoc['targetEntity']);
|
||||
foreach ($assoc['orderBy'] AS $orderField => $orientation) {
|
||||
if (!$targetClass->hasField($orderField)) {
|
||||
$ce[] = "The association " . $class->name."#".$fieldName." is ordered by a foreign field " .
|
||||
$orderField . " that is not a field on the target entity " . $targetClass->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($class->reflClass->getProperties(\ReflectionProperty::IS_PUBLIC) as $publicAttr) {
|
||||
if ($publicAttr->isStatic()) {
|
||||
continue;
|
||||
}
|
||||
$ce[] = "Field '".$publicAttr->getName()."' in class '".$class->name."' must be private ".
|
||||
"or protected. Public fields may break lazy-loading.";
|
||||
}
|
||||
|
||||
foreach ($class->subClasses AS $subClass) {
|
||||
if (!in_array($class->name, class_parents($subClass))) {
|
||||
$ce[] = "According to the discriminator map class '" . $subClass . "' has to be a child ".
|
||||
"of '" . $class->name . "' but these entities are not related through inheritance.";
|
||||
}
|
||||
}
|
||||
|
||||
if ($ce) {
|
||||
if ($ce = $this->validateClass($class)) {
|
||||
$errors[$class->name] = $ce;
|
||||
}
|
||||
}
|
||||
@ -220,6 +77,170 @@ class SchemaValidator
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a single class of the current
|
||||
*
|
||||
* @param ClassMetadataInfo $class
|
||||
* @return array
|
||||
*/
|
||||
public function validateClass(ClassMetadataInfo $class)
|
||||
{
|
||||
$ce = array();
|
||||
$cmf = $this->em->getMetadataFactory();
|
||||
|
||||
foreach ($class->associationMappings AS $fieldName => $assoc) {
|
||||
if (!$cmf->hasMetadataFor($assoc['targetEntity'])) {
|
||||
$ce[] = "The target entity '" . $assoc['targetEntity'] . "' specified on " . $class->name . '#' . $fieldName . ' is unknown.';
|
||||
return $ce;
|
||||
}
|
||||
|
||||
if ($assoc['mappedBy'] && $assoc['inversedBy']) {
|
||||
$ce[] = "The association " . $class . "#" . $fieldName . " cannot be defined as both inverse and owning.";
|
||||
}
|
||||
|
||||
$targetMetadata = $cmf->getMetadataFor($assoc['targetEntity']);
|
||||
|
||||
/* @var $assoc AssociationMapping */
|
||||
if ($assoc['mappedBy']) {
|
||||
if ($targetMetadata->hasField($assoc['mappedBy'])) {
|
||||
$ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the owning side ".
|
||||
"field " . $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " which is not defined as association.";
|
||||
}
|
||||
if (!$targetMetadata->hasAssociation($assoc['mappedBy'])) {
|
||||
$ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the owning side ".
|
||||
"field " . $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " which does not exist.";
|
||||
} else if ($targetMetadata->associationMappings[$assoc['mappedBy']]['inversedBy'] == null) {
|
||||
$ce[] = "The field " . $class->name . "#" . $fieldName . " is on the inverse side of a ".
|
||||
"bi-directional relationship, but the specified mappedBy association on the target-entity ".
|
||||
$assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " does not contain the required ".
|
||||
"'inversedBy' attribute.";
|
||||
} else if ($targetMetadata->associationMappings[$assoc['mappedBy']]['inversedBy'] != $fieldName) {
|
||||
$ce[] = "The mappings " . $class->name . "#" . $fieldName . " and " .
|
||||
$assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " are ".
|
||||
"incosistent with each other.";
|
||||
}
|
||||
}
|
||||
|
||||
if ($assoc['inversedBy']) {
|
||||
if ($targetMetadata->hasField($assoc['inversedBy'])) {
|
||||
$ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the inverse side ".
|
||||
"field " . $assoc['targetEntity'] . "#" . $assoc['inversedBy'] . " which is not defined as association.";
|
||||
}
|
||||
if (!$targetMetadata->hasAssociation($assoc['inversedBy'])) {
|
||||
$ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the inverse side ".
|
||||
"field " . $assoc['targetEntity'] . "#" . $assoc['inversedBy'] . " which does not exist.";
|
||||
} else if ($targetMetadata->associationMappings[$assoc['inversedBy']]['mappedBy'] == null) {
|
||||
$ce[] = "The field " . $class->name . "#" . $fieldName . " is on the owning side of a ".
|
||||
"bi-directional relationship, but the specified mappedBy association on the target-entity ".
|
||||
$assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " does not contain the required ".
|
||||
"'inversedBy' attribute.";
|
||||
} else if ($targetMetadata->associationMappings[$assoc['inversedBy']]['mappedBy'] != $fieldName) {
|
||||
$ce[] = "The mappings " . $class->name . "#" . $fieldName . " and " .
|
||||
$assoc['targetEntity'] . "#" . $assoc['inversedBy'] . " are ".
|
||||
"incosistent with each other.";
|
||||
}
|
||||
}
|
||||
|
||||
if ($assoc['isOwningSide']) {
|
||||
if ($assoc['type'] == ClassMetadataInfo::MANY_TO_MANY) {
|
||||
foreach ($assoc['joinTable']['joinColumns'] AS $joinColumn) {
|
||||
if (!isset($class->fieldNames[$joinColumn['referencedColumnName']])) {
|
||||
$ce[] = "The referenced column name '" . $joinColumn['referencedColumnName'] . "' does not " .
|
||||
"have a corresponding field with this column name on the class '" . $class->name . "'.";
|
||||
break;
|
||||
}
|
||||
|
||||
$fieldName = $class->fieldNames[$joinColumn['referencedColumnName']];
|
||||
if (!in_array($fieldName, $class->identifier)) {
|
||||
$ce[] = "The referenced column name '" . $joinColumn['referencedColumnName'] . "' " .
|
||||
"has to be a primary key column.";
|
||||
}
|
||||
}
|
||||
foreach ($assoc['joinTable']['inverseJoinColumns'] AS $inverseJoinColumn) {
|
||||
if (!isset($targetMetadata->fieldNames[$inverseJoinColumn['referencedColumnName']])) {
|
||||
$ce[] = "The inverse referenced column name '" . $inverseJoinColumn['referencedColumnName'] . "' does not " .
|
||||
"have a corresponding field with this column name on the class '" . $targetMetadata->name . "'.";
|
||||
break;
|
||||
}
|
||||
|
||||
$fieldName = $targetMetadata->fieldNames[$inverseJoinColumn['referencedColumnName']];
|
||||
if (!in_array($fieldName, $targetMetadata->identifier)) {
|
||||
$ce[] = "The referenced column name '" . $inverseJoinColumn['referencedColumnName'] . "' " .
|
||||
"has to be a primary key column.";
|
||||
}
|
||||
}
|
||||
|
||||
if (count($targetMetadata->getIdentifierColumnNames()) != count($assoc['joinTable']['inverseJoinColumns'])) {
|
||||
$ce[] = "The inverse join columns of the many-to-many table '" . $assoc['joinTable']['name'] . "' " .
|
||||
"have to contain to ALL identifier columns of the target entity '". $targetMetadata->name . "', " .
|
||||
"however '" . implode(", ", array_diff($targetMetadata->getIdentifierColumnNames(), array_values($assoc['relationToTargetKeyColumns']))) .
|
||||
"' are missing.";
|
||||
}
|
||||
|
||||
if (count($class->getIdentifierColumnNames()) != count($assoc['joinTable']['joinColumns'])) {
|
||||
$ce[] = "The join columns of the many-to-many table '" . $assoc['joinTable']['name'] . "' " .
|
||||
"have to contain to ALL identifier columns of the source entity '". $class->name . "', " .
|
||||
"however '" . implode(", ", array_diff($class->getIdentifierColumnNames(), array_values($assoc['relationToSourceKeyColumns']))) .
|
||||
"' are missing.";
|
||||
}
|
||||
|
||||
} else if ($assoc['type'] & ClassMetadataInfo::TO_ONE) {
|
||||
foreach ($assoc['joinColumns'] AS $joinColumn) {
|
||||
if (!isset($targetMetadata->fieldNames[$joinColumn['referencedColumnName']])) {
|
||||
$ce[] = "The referenced column name '" . $joinColumn['referencedColumnName'] . "' does not " .
|
||||
"have a corresponding field with this column name on the class '" . $targetMetadata->name . "'.";
|
||||
break;
|
||||
}
|
||||
|
||||
$fieldName = $targetMetadata->fieldNames[$joinColumn['referencedColumnName']];
|
||||
if (!in_array($fieldName, $targetMetadata->identifier)) {
|
||||
$ce[] = "The referenced column name '" . $joinColumn['referencedColumnName'] . "' " .
|
||||
"has to be a primary key column.";
|
||||
}
|
||||
}
|
||||
|
||||
if (count($class->getIdentifierColumnNames()) != count($assoc['joinColumns'])) {
|
||||
$ids = array();
|
||||
foreach ($assoc['joinColumns'] AS $joinColumn) {
|
||||
$ids[] = $joinColumn['name'];
|
||||
}
|
||||
|
||||
$ce[] = "The join columns of the association '" . $assoc['fieldName'] . "' " .
|
||||
"have to match to ALL identifier columns of the source entity '". $class->name . "', " .
|
||||
"however '" . implode(", ", array_diff($class->getIdentifierColumnNames(), $ids)) .
|
||||
"' are missing.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($assoc['orderBy']) && $assoc['orderBy'] !== null) {
|
||||
foreach ($assoc['orderBy'] AS $orderField => $orientation) {
|
||||
if (!$targetMetadata->hasField($orderField)) {
|
||||
$ce[] = "The association " . $class->name."#".$fieldName." is ordered by a foreign field " .
|
||||
$orderField . " that is not a field on the target entity " . $targetMetadata->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($class->reflClass->getProperties(\ReflectionProperty::IS_PUBLIC) as $publicAttr) {
|
||||
if ($publicAttr->isStatic()) {
|
||||
continue;
|
||||
}
|
||||
$ce[] = "Field '".$publicAttr->getName()."' in class '".$class->name."' must be private ".
|
||||
"or protected. Public fields may break lazy-loading.";
|
||||
}
|
||||
|
||||
foreach ($class->subClasses AS $subClass) {
|
||||
if (!in_array($class->name, class_parents($subClass))) {
|
||||
$ce[] = "According to the discriminator map class '" . $subClass . "' has to be a child ".
|
||||
"of '" . $class->name . "' but these entities are not related through inheritance.";
|
||||
}
|
||||
}
|
||||
|
||||
return $ce;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the Database Schema is in sync with the current metadata state.
|
||||
*
|
||||
@ -230,6 +251,6 @@ class SchemaValidator
|
||||
$schemaTool = new SchemaTool($this->em);
|
||||
|
||||
$allMetadata = $this->em->getMetadataFactory()->getAllMetadata();
|
||||
return (count($schemaTool->getUpdateSchemaSql($allMetadata, false)) == 0);
|
||||
return (count($schemaTool->getUpdateSchemaSql($allMetadata, true)) == 0);
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,38 @@
|
||||
<?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\Tools;
|
||||
|
||||
use Doctrine\ORM\ORMException;
|
||||
|
||||
/**
|
||||
* Tools related Exceptions
|
||||
*
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class ToolsException extends ORMException
|
||||
{
|
||||
public static function schemaToolFailure($sql, \Exception $e)
|
||||
{
|
||||
return new self("Schema-Tool failed with Error '" . $e->getMessage() . "' while executing DDL: " . $sql, "0", $e);
|
||||
}
|
||||
|
||||
public static function couldNotMapDoctrine1Type($type)
|
||||
{
|
||||
return new self("Could not map doctrine 1 type '$type'!");
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,7 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
|
||||
private $_platformMock;
|
||||
private $_lastInsertId = 0;
|
||||
private $_inserts = array();
|
||||
|
||||
|
||||
public function __construct(array $params, $driver, $config = null, $eventManager = null)
|
||||
{
|
||||
$this->_platformMock = new DatabasePlatformMock();
|
||||
@ -18,7 +18,7 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
|
||||
// Override possible assignment of platform to database platform mock
|
||||
$this->_platform = $this->_platformMock;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
@ -26,15 +26,15 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
|
||||
{
|
||||
return $this->_platformMock;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public function insert($tableName, array $data)
|
||||
public function insert($tableName, array $data, array $types = array())
|
||||
{
|
||||
$this->_inserts[$tableName][] = $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
@ -50,7 +50,7 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
|
||||
{
|
||||
return $this->_fetchOneResult;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
@ -61,29 +61,29 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
|
||||
}
|
||||
return $input;
|
||||
}
|
||||
|
||||
|
||||
/* Mock API */
|
||||
|
||||
public function setFetchOneResult($fetchOneResult)
|
||||
{
|
||||
$this->_fetchOneResult = $fetchOneResult;
|
||||
}
|
||||
|
||||
|
||||
public function setDatabasePlatform($platform)
|
||||
{
|
||||
$this->_platformMock = $platform;
|
||||
}
|
||||
|
||||
|
||||
public function setLastInsertId($id)
|
||||
{
|
||||
$this->_lastInsertId = $id;
|
||||
}
|
||||
|
||||
|
||||
public function getInserts()
|
||||
{
|
||||
return $this->_inserts;
|
||||
}
|
||||
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->_inserts = array();
|
||||
|
@ -57,7 +57,7 @@ class DatabasePlatformMock extends \Doctrine\DBAL\Platforms\AbstractPlatform
|
||||
|
||||
/** @override */
|
||||
public function getVarcharTypeDeclarationSQL(array $field) {}
|
||||
|
||||
|
||||
/** @override */
|
||||
public function getClobTypeDeclarationSQL(array $field) {}
|
||||
|
||||
@ -85,6 +85,13 @@ class DatabasePlatformMock extends \Doctrine\DBAL\Platforms\AbstractPlatform
|
||||
|
||||
protected function initializeDoctrineTypeMappings()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
/**
|
||||
* Gets the SQL Snippet used to declare a BLOB column type.
|
||||
*/
|
||||
public function getBlobTypeDeclarationSQL(array $field)
|
||||
{
|
||||
throw DBALException::notSupported(__METHOD__);
|
||||
}
|
||||
}
|
@ -8,10 +8,10 @@ namespace Doctrine\Tests\Mocks;
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class HydratorMockStatement implements \Doctrine\DBAL\Driver\Statement
|
||||
class HydratorMockStatement implements \IteratorAggregate, \Doctrine\DBAL\Driver\Statement
|
||||
{
|
||||
private $_resultSet;
|
||||
|
||||
private $_resultSet;
|
||||
|
||||
/**
|
||||
* Creates a new mock statement that will serve the provided fake result set to clients.
|
||||
*
|
||||
@ -21,7 +21,7 @@ class HydratorMockStatement implements \Doctrine\DBAL\Driver\Statement
|
||||
{
|
||||
$this->_resultSet = $resultSet;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches all rows from the result set.
|
||||
*
|
||||
@ -31,7 +31,7 @@ class HydratorMockStatement implements \Doctrine\DBAL\Driver\Statement
|
||||
{
|
||||
return $this->_resultSet;
|
||||
}
|
||||
|
||||
|
||||
public function fetchColumn($columnNumber = 0)
|
||||
{
|
||||
$row = current($this->_resultSet);
|
||||
@ -39,10 +39,10 @@ class HydratorMockStatement implements \Doctrine\DBAL\Driver\Statement
|
||||
$val = array_shift($row);
|
||||
return $val !== null ? $val : false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the next row in the result set.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public function fetch($fetchStyle = null)
|
||||
{
|
||||
@ -50,7 +50,7 @@ class HydratorMockStatement implements \Doctrine\DBAL\Driver\Statement
|
||||
next($this->_resultSet);
|
||||
return $current;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closes the cursor, enabling the statement to be executed again.
|
||||
*
|
||||
@ -60,13 +60,13 @@ class HydratorMockStatement implements \Doctrine\DBAL\Driver\Statement
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function setResultSet(array $resultSet)
|
||||
{
|
||||
reset($resultSet);
|
||||
$this->_resultSet = $resultSet;
|
||||
}
|
||||
|
||||
|
||||
public function bindColumn($column, &$param, $type = null)
|
||||
{
|
||||
}
|
||||
@ -78,7 +78,7 @@ class HydratorMockStatement implements \Doctrine\DBAL\Driver\Statement
|
||||
public function bindParam($column, &$variable, $type = null, $length = null, $driverOptions = array())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public function columnCount()
|
||||
{
|
||||
}
|
||||
@ -86,16 +86,26 @@ class HydratorMockStatement implements \Doctrine\DBAL\Driver\Statement
|
||||
public function errorCode()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public function errorInfo()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public function execute($params = array())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public function rowCount()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public function getIterator()
|
||||
{
|
||||
return $this->_resultSet;
|
||||
}
|
||||
|
||||
public function setFetchMode($fetchMode)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -46,7 +46,7 @@ class CmsAddress
|
||||
public function getId() {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
|
||||
public function getUser() {
|
||||
return $this->user;
|
||||
}
|
||||
@ -62,7 +62,7 @@ class CmsAddress
|
||||
public function getCity() {
|
||||
return $this->city;
|
||||
}
|
||||
|
||||
|
||||
public function setUser(CmsUser $user) {
|
||||
if ($this->user !== $user) {
|
||||
$this->user = $user;
|
||||
|
@ -9,6 +9,7 @@ class DDC117Article
|
||||
{
|
||||
/** @Id @Column(type="integer", name="article_id") @GeneratedValue */
|
||||
private $id;
|
||||
|
||||
/** @Column */
|
||||
private $title;
|
||||
|
||||
|
@ -0,0 +1,76 @@
|
||||
<?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\Tests\Models\DDC1476;
|
||||
|
||||
/**
|
||||
* @Entity()
|
||||
*/
|
||||
class DDC1476EntityWithDefaultFieldType
|
||||
{
|
||||
|
||||
/**
|
||||
* @Id
|
||||
* @Column()
|
||||
* @GeneratedValue("NONE")
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/** @column() */
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public static function loadMetadata(\Doctrine\ORM\Mapping\ClassMetadataInfo $metadata)
|
||||
{
|
||||
$metadata->mapField(array(
|
||||
'id' => true,
|
||||
'fieldName' => 'id',
|
||||
));
|
||||
$metadata->mapField(array(
|
||||
'fieldName' => 'name',
|
||||
));
|
||||
|
||||
$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadataInfo::GENERATOR_TYPE_NONE);
|
||||
}
|
||||
|
||||
}
|
@ -21,7 +21,7 @@ class LegacyUser
|
||||
*/
|
||||
public $_username;
|
||||
/**
|
||||
* @Column(type="string", length=255)
|
||||
* @Column(type="string", length=255, name="name")
|
||||
*/
|
||||
public $_name;
|
||||
/**
|
||||
|
@ -23,12 +23,12 @@ class LegacyUserReference
|
||||
private $_target;
|
||||
|
||||
/**
|
||||
* @column(type="string")
|
||||
* @column(type="string", name="description")
|
||||
*/
|
||||
private $_description;
|
||||
|
||||
/**
|
||||
* @column(type="datetime")
|
||||
* @column(type="datetime", name="created")
|
||||
*/
|
||||
private $_created;
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* 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
|
||||
@ -33,11 +31,13 @@ require_once __DIR__ . '/../../TestInit.php';
|
||||
* @link http://www.doctrine-project.org
|
||||
* @since 2.0
|
||||
*/
|
||||
class CustomTreeWalkersTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
class CustomTreeWalkersTest extends \Doctrine\Tests\OrmTestCase
|
||||
{
|
||||
protected function setUp() {
|
||||
$this->useModelSet('cms');
|
||||
parent::setUp();
|
||||
private $_em;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->_em = $this->_getTestEntityManager();
|
||||
}
|
||||
|
||||
public function assertSqlGeneration($dqlToBeTested, $sqlToBeConfirmed)
|
||||
@ -70,7 +70,7 @@ class CustomTreeWalkersTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
"SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3, c0_.email_id AS email_id4 FROM cms_users c0_ WHERE (c0_.name = ? OR c0_.name = ?) AND c0_.id = 1"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function testSupportsQueriesWithSimpleConditionalExpression()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
@ -94,7 +94,7 @@ class CustomTreeWalker extends Query\TreeWalkerAdapter
|
||||
$dqlAliases[] = $dqlAlias;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Create our conditions for all involved classes
|
||||
$factors = array();
|
||||
foreach ($dqlAliases as $alias) {
|
||||
@ -108,7 +108,7 @@ class CustomTreeWalker extends Query\TreeWalkerAdapter
|
||||
$factor = new Query\AST\ConditionalFactor($condPrimary);
|
||||
$factors[] = $factor;
|
||||
}
|
||||
|
||||
|
||||
if (($whereClause = $selectStatement->whereClause) !== null) {
|
||||
// There is already a WHERE clause, so append the conditions
|
||||
$condExpr = $whereClause->conditionalExpression;
|
||||
@ -119,18 +119,18 @@ class CustomTreeWalker extends Query\TreeWalkerAdapter
|
||||
|
||||
$whereClause->conditionalExpression = $condExpr;
|
||||
}
|
||||
|
||||
|
||||
$existingTerms = $whereClause->conditionalExpression->conditionalTerms;
|
||||
|
||||
|
||||
if (count($existingTerms) > 1) {
|
||||
// More than one term, so we need to wrap all these terms in a single root term
|
||||
// i.e: "WHERE u.name = :foo or u.other = :bar" => "WHERE (u.name = :foo or u.other = :bar) AND <our condition>"
|
||||
|
||||
|
||||
$primary = new Query\AST\ConditionalPrimary;
|
||||
$primary->conditionalExpression = new Query\AST\ConditionalExpression($existingTerms);
|
||||
$existingFactor = new Query\AST\ConditionalFactor($primary);
|
||||
$term = new Query\AST\ConditionalTerm(array_merge(array($existingFactor), $factors));
|
||||
|
||||
|
||||
$selectStatement->whereClause->conditionalExpression->conditionalTerms = array($term);
|
||||
} else {
|
||||
// Just one term so we can simply append our factors to that term
|
||||
|
@ -20,7 +20,9 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
$this->_em->getConfiguration()->setEntityNamespaces(array());
|
||||
if ($this->_em) {
|
||||
$this->_em->getConfiguration()->setEntityNamespaces(array());
|
||||
}
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
@ -78,7 +80,7 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
return array($user->id, $address->id);
|
||||
}
|
||||
|
||||
|
||||
public function buildUser($name, $username, $status, $address)
|
||||
{
|
||||
$user = new CmsUser();
|
||||
@ -89,10 +91,10 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
|
||||
public function buildAddress($country, $city, $street, $zip)
|
||||
{
|
||||
$address = new CmsAddress();
|
||||
@ -103,7 +105,7 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$this->_em->persist($address);
|
||||
$this->_em->flush();
|
||||
|
||||
|
||||
return $address;
|
||||
}
|
||||
|
||||
@ -134,22 +136,22 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
$address1 = $this->buildAddress('Germany', 'Berlim', 'Foo st.', '123456');
|
||||
$user1 = $this->buildUser('Benjamin', 'beberlei', 'dev', $address1);
|
||||
|
||||
|
||||
$address2 = $this->buildAddress('Brazil', 'São Paulo', 'Bar st.', '654321');
|
||||
$user2 = $this->buildUser('Guilherme', 'guilhermeblanco', 'freak', $address2);
|
||||
|
||||
|
||||
$address3 = $this->buildAddress('USA', 'Nashville', 'Woo st.', '321654');
|
||||
$user3 = $this->buildUser('Jonathan', 'jwage', 'dev', $address3);
|
||||
|
||||
|
||||
unset($address1);
|
||||
unset($address2);
|
||||
unset($address3);
|
||||
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
$repository = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsAddress');
|
||||
$addresses = $repository->findBy(array('user' => array($user1->getId(), $user2->getId())));
|
||||
|
||||
|
||||
$this->assertEquals(2, count($addresses));
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsAddress',$addresses[0]);
|
||||
}
|
||||
@ -158,22 +160,22 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
$address1 = $this->buildAddress('Germany', 'Berlim', 'Foo st.', '123456');
|
||||
$user1 = $this->buildUser('Benjamin', 'beberlei', 'dev', $address1);
|
||||
|
||||
|
||||
$address2 = $this->buildAddress('Brazil', 'São Paulo', 'Bar st.', '654321');
|
||||
$user2 = $this->buildUser('Guilherme', 'guilhermeblanco', 'freak', $address2);
|
||||
|
||||
|
||||
$address3 = $this->buildAddress('USA', 'Nashville', 'Woo st.', '321654');
|
||||
$user3 = $this->buildUser('Jonathan', 'jwage', 'dev', $address3);
|
||||
|
||||
|
||||
unset($address1);
|
||||
unset($address2);
|
||||
unset($address3);
|
||||
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
$repository = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsAddress');
|
||||
$addresses = $repository->findBy(array('user' => array($user1, $user2)));
|
||||
|
||||
|
||||
$this->assertEquals(2, count($addresses));
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsAddress',$addresses[0]);
|
||||
}
|
||||
@ -189,7 +191,7 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertEquals('Guilherme', $users[0]->name);
|
||||
$this->assertEquals('dev', $users[0]->status);
|
||||
}
|
||||
|
||||
|
||||
public function testFindAll()
|
||||
{
|
||||
$user1Id = $this->loadFixture();
|
||||
@ -280,7 +282,7 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$userId = $user->id;
|
||||
|
||||
$this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $userId);
|
||||
|
||||
|
||||
$this->setExpectedException('Doctrine\ORM\OptimisticLockException');
|
||||
$this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $userId, \Doctrine\DBAL\LockMode::OPTIMISTIC);
|
||||
}
|
||||
@ -423,7 +425,7 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
public function testFindByLimitOffset()
|
||||
{
|
||||
$this->loadFixture();
|
||||
|
||||
|
||||
$repos = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser');
|
||||
|
||||
$users1 = $repos->findBy(array(), null, 1, 0);
|
||||
@ -451,8 +453,8 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertSame($usersAsc[0], $usersDesc[2]);
|
||||
$this->assertSame($usersAsc[2], $usersDesc[0]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-753
|
||||
*/
|
||||
@ -465,19 +467,19 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$repos = $this->_em->getRepository('Doctrine\Tests\Models\DDC753\DDC753EntityWithDefaultCustomRepository');
|
||||
$this->assertInstanceOf("Doctrine\Tests\Models\DDC753\DDC753DefaultRepository", $repos);
|
||||
$this->assertTrue($repos->isDefaultRepository());
|
||||
|
||||
|
||||
|
||||
|
||||
$repos = $this->_em->getRepository('Doctrine\Tests\Models\DDC753\DDC753EntityWithCustomRepository');
|
||||
$this->assertInstanceOf("Doctrine\Tests\Models\DDC753\DDC753CustomRepository", $repos);
|
||||
$this->assertTrue($repos->isCustomRepository());
|
||||
|
||||
|
||||
$this->assertEquals($this->_em->getConfiguration()->getDefaultRepositoryClassName(), "Doctrine\Tests\Models\DDC753\DDC753DefaultRepository");
|
||||
$this->_em->getConfiguration()->setDefaultRepositoryClassName("Doctrine\ORM\EntityRepository");
|
||||
$this->assertEquals($this->_em->getConfiguration()->getDefaultRepositoryClassName(), "Doctrine\ORM\EntityRepository");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-753
|
||||
* @expectedException Doctrine\ORM\ORMException
|
||||
@ -488,6 +490,6 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertEquals($this->_em->getConfiguration()->getDefaultRepositoryClassName(), "Doctrine\ORM\EntityRepository");
|
||||
$this->_em->getConfiguration()->setDefaultRepositoryClassName("Doctrine\Tests\Models\DDC753\DDC753InvalidRepository");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsGroup');
|
||||
$class->associationMappings['users']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
|
||||
|
||||
|
||||
|
||||
$this->loadFixture();
|
||||
}
|
||||
|
||||
@ -137,9 +137,9 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
|
||||
$this->assertFalse($user->groups->isInitialized(), "Pre-Condition: Collection is not initialized.");
|
||||
|
||||
|
||||
$queryCount = $this->getCurrentQueryCount();
|
||||
|
||||
|
||||
$someGroups = $user->groups->slice(0, 2);
|
||||
|
||||
$this->assertContainsOnly('Doctrine\Tests\Models\CMS\CmsGroup', $someGroups);
|
||||
@ -225,7 +225,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertFalse($user->articles->isInitialized(), "Pre-Condition: Collection is not initialized.");
|
||||
|
||||
$article = $this->_em->find('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId);
|
||||
|
||||
|
||||
$queryCount = $this->getCurrentQueryCount();
|
||||
$this->assertTrue($user->articles->contains($article));
|
||||
$this->assertFalse($user->articles->isInitialized(), "Post-Condition: Collection is not initialized.");
|
||||
@ -304,6 +304,49 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertFalse($user->groups->isInitialized(), "Post-Condition: Collection is not initialized.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1399
|
||||
*/
|
||||
public function testCountAfterAddThenFlush()
|
||||
{
|
||||
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
|
||||
|
||||
$newGroup = new \Doctrine\Tests\Models\CMS\CmsGroup();
|
||||
$newGroup->name = "Test4";
|
||||
|
||||
$user->addGroup($newGroup);
|
||||
$this->_em->persist($newGroup);
|
||||
|
||||
$this->assertFalse($user->groups->isInitialized());
|
||||
$this->assertEquals(4, count($user->groups));
|
||||
$this->assertFalse($user->groups->isInitialized());
|
||||
|
||||
$this->_em->flush();
|
||||
|
||||
$this->assertEquals(4, count($user->groups));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1462
|
||||
*/
|
||||
public function testSliceOnDirtyCollection()
|
||||
{
|
||||
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
|
||||
/* @var $user CmsUser */
|
||||
|
||||
$newGroup = new \Doctrine\Tests\Models\CMS\CmsGroup();
|
||||
$newGroup->name = "Test4";
|
||||
|
||||
$user->addGroup($newGroup);
|
||||
$this->_em->persist($newGroup);
|
||||
|
||||
$qc = $this->getCurrentQueryCount();
|
||||
$groups = $user->groups->slice(0, 10);
|
||||
|
||||
$this->assertEquals(4, count($groups));
|
||||
$this->assertEquals($qc + 1, $this->getCurrentQueryCount());
|
||||
}
|
||||
|
||||
private function loadFixture()
|
||||
{
|
||||
$user1 = new \Doctrine\Tests\Models\CMS\CmsUser();
|
||||
@ -364,7 +407,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$this->_em->persist($article1);
|
||||
$this->_em->persist($article2);
|
||||
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
|
@ -43,6 +43,29 @@ class LifecycleCallbackTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertEquals('changed from preUpdate callback!', $result[0]->value);
|
||||
}
|
||||
|
||||
public function testPreFlushCallbacksAreInvoked()
|
||||
{
|
||||
$entity = new LifecycleCallbackTestEntity;
|
||||
$entity->value = 'hello';
|
||||
$this->_em->persist($entity);
|
||||
|
||||
$this->_em->flush();
|
||||
|
||||
$this->assertTrue($entity->prePersistCallbackInvoked);
|
||||
$this->assertTrue($entity->preFlushCallbackInvoked);
|
||||
|
||||
$entity->preFlushCallbackInvoked = false;
|
||||
$this->_em->flush();
|
||||
|
||||
$this->assertTrue($entity->preFlushCallbackInvoked);
|
||||
|
||||
$entity->value = 'bye';
|
||||
$entity->preFlushCallbackInvoked = false;
|
||||
$this->_em->flush();
|
||||
|
||||
$this->assertTrue($entity->preFlushCallbackInvoked);
|
||||
}
|
||||
|
||||
public function testChangesDontGetLost()
|
||||
{
|
||||
$user = new LifecycleCallbackTestUser;
|
||||
@ -190,6 +213,8 @@ class LifecycleCallbackTestEntity
|
||||
public $postPersistCallbackInvoked = false;
|
||||
public $postLoadCallbackInvoked = false;
|
||||
|
||||
public $preFlushCallbackInvoked = false;
|
||||
|
||||
/**
|
||||
* @Id @Column(type="integer")
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
@ -233,6 +258,11 @@ class LifecycleCallbackTestEntity
|
||||
public function doStuffOnPreUpdate() {
|
||||
$this->value = 'changed from preUpdate callback!';
|
||||
}
|
||||
|
||||
/** @PreFlush */
|
||||
public function doStuffOnPreFlush() {
|
||||
$this->preFlushCallbackInvoked = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,6 +39,7 @@ class MappedSuperclassTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$cleanFile = $this->_em->find(get_class($file), $file->getId());
|
||||
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\DirectoryTree\Directory', $cleanFile->getParent());
|
||||
$this->assertInstanceOf('Doctrine\ORM\Proxy\Proxy', $cleanFile->getParent());
|
||||
$this->assertEquals($directory->getId(), $cleanFile->getParent()->getId());
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\DirectoryTree\Directory', $cleanFile->getParent()->getParent());
|
||||
$this->assertEquals($root->getId(), $cleanFile->getParent()->getParent()->getId());
|
||||
|
@ -35,7 +35,7 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$user->status = 'dev';
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
$rsm = new ResultSetMapping;
|
||||
@ -94,24 +94,24 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertEquals($addr->street, $addresses[0]->street);
|
||||
$this->assertTrue($addresses[0]->user instanceof CmsUser);
|
||||
}
|
||||
|
||||
|
||||
public function testJoinedOneToManyNativeQuery()
|
||||
{
|
||||
$user = new CmsUser;
|
||||
$user->name = 'Roman';
|
||||
$user->username = 'romanb';
|
||||
$user->status = 'dev';
|
||||
|
||||
|
||||
$phone = new CmsPhonenumber;
|
||||
$phone->phonenumber = 424242;
|
||||
|
||||
|
||||
$user->addPhonenumber($phone);
|
||||
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addFieldResult('u', $this->platform->getSQLResultCasing('id'), 'id');
|
||||
@ -119,7 +119,7 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$rsm->addFieldResult('u', $this->platform->getSQLResultCasing('status'), 'status');
|
||||
$rsm->addJoinedEntityResult('Doctrine\Tests\Models\CMS\CmsPhonenumber', 'p', 'u', 'phonenumbers');
|
||||
$rsm->addFieldResult('p', $this->platform->getSQLResultCasing('phonenumber'), 'phonenumber');
|
||||
|
||||
|
||||
$query = $this->_em->createNativeQuery('SELECT id, name, status, phonenumber FROM cms_users INNER JOIN cms_phonenumbers ON id = user_id WHERE username = ?', $rsm);
|
||||
$query->setParameter(1, 'romanb');
|
||||
|
||||
@ -133,30 +133,30 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$phones = $users[0]->getPhonenumbers();
|
||||
$this->assertEquals(424242, $phones[0]->phonenumber);
|
||||
$this->assertTrue($phones[0]->getUser() === $users[0]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function testJoinedOneToOneNativeQuery()
|
||||
{
|
||||
$user = new CmsUser;
|
||||
$user->name = 'Roman';
|
||||
$user->username = 'romanb';
|
||||
$user->status = 'dev';
|
||||
|
||||
|
||||
$addr = new CmsAddress;
|
||||
$addr->country = 'germany';
|
||||
$addr->zip = 10827;
|
||||
$addr->city = 'Berlin';
|
||||
|
||||
|
||||
|
||||
|
||||
$user->setAddress($addr);
|
||||
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
|
||||
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addFieldResult('u', $this->platform->getSQLResultCasing('id'), 'id');
|
||||
@ -167,12 +167,12 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$rsm->addFieldResult('a', $this->platform->getSQLResultCasing('country'), 'country');
|
||||
$rsm->addFieldResult('a', $this->platform->getSQLResultCasing('zip'), 'zip');
|
||||
$rsm->addFieldResult('a', $this->platform->getSQLResultCasing('city'), 'city');
|
||||
|
||||
|
||||
$query = $this->_em->createNativeQuery('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 = ?', $rsm);
|
||||
$query->setParameter(1, 'romanb');
|
||||
|
||||
|
||||
$users = $query->getResult();
|
||||
|
||||
|
||||
$this->assertEquals(1, count($users));
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $users[0]);
|
||||
$this->assertEquals('Roman', $users[0]->name);
|
||||
|
@ -73,7 +73,14 @@ class OneToManyUnidirectionalAssociationTest extends \Doctrine\Tests\OrmFunction
|
||||
$this->_em->persist($routeA);
|
||||
$this->_em->persist($routeB);
|
||||
|
||||
$this->setExpectedException('Exception'); // depends on the underyling Database Driver
|
||||
$this->_em->flush(); // Exception
|
||||
$exceptionThrown = false;
|
||||
try {
|
||||
// exception depending on the underyling Database Driver
|
||||
$this->_em->flush();
|
||||
} catch(\Exception $e) {
|
||||
$exceptionThrown = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($exceptionThrown, "The underlying database driver throws an exception.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ class OneToOneEagerLoadingTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Train'),
|
||||
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\TrainDriver'),
|
||||
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\TrainOwner'),
|
||||
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Waggon'),
|
||||
));
|
||||
} catch(\Exception $e) {}
|
||||
@ -26,7 +27,7 @@ class OneToOneEagerLoadingTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
public function testEagerLoadOneToOneOwningSide()
|
||||
{
|
||||
$train = new Train();
|
||||
$train = new Train(new TrainOwner("Alexander"));
|
||||
$driver = new TrainDriver("Benjamin");
|
||||
$waggon = new Waggon();
|
||||
|
||||
@ -48,7 +49,7 @@ class OneToOneEagerLoadingTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
public function testEagerLoadOneToOneNullOwningSide()
|
||||
{
|
||||
$train = new Train();
|
||||
$train = new Train(new TrainOwner("Alexander"));
|
||||
|
||||
$this->_em->persist($train); // cascades
|
||||
$this->_em->flush();
|
||||
@ -65,9 +66,8 @@ class OneToOneEagerLoadingTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
public function testEagerLoadOneToOneInverseSide()
|
||||
{
|
||||
$train = new Train();
|
||||
$driver = new TrainDriver("Benjamin");
|
||||
$train->setDriver($driver);
|
||||
$owner = new TrainOwner("Alexander");
|
||||
$train = new Train($owner);
|
||||
|
||||
$this->_em->persist($train); // cascades
|
||||
$this->_em->flush();
|
||||
@ -75,9 +75,9 @@ class OneToOneEagerLoadingTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$sqlCount = count($this->_sqlLoggerStack->queries);
|
||||
|
||||
$driver = $this->_em->find(get_class($driver), $driver->id);
|
||||
$this->assertNotInstanceOf('Doctrine\ORM\Proxy\Proxy', $driver->train);
|
||||
$this->assertNotNull($driver->train);
|
||||
$driver = $this->_em->find(get_class($owner), $owner->id);
|
||||
$this->assertNotInstanceOf('Doctrine\ORM\Proxy\Proxy', $owner->train);
|
||||
$this->assertNotNull($owner->train);
|
||||
|
||||
$this->assertEquals($sqlCount + 1, count($this->_sqlLoggerStack->queries));
|
||||
}
|
||||
@ -103,7 +103,7 @@ class OneToOneEagerLoadingTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
public function testEagerLoadManyToOne()
|
||||
{
|
||||
$train = new Train();
|
||||
$train = new Train(new TrainOwner("Alexander"));
|
||||
$waggon = new Waggon();
|
||||
$train->addWaggon($waggon);
|
||||
|
||||
@ -115,6 +115,59 @@ class OneToOneEagerLoadingTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertNotInstanceOf('Doctrine\ORM\Proxy\Proxy', $waggon->train);
|
||||
$this->assertNotNull($waggon->train);
|
||||
}
|
||||
|
||||
public function testEagerLoadWithNullableColumnsGeneratesLeftJoinOnBothSides()
|
||||
{
|
||||
$train = new Train(new TrainOwner("Alexander"));
|
||||
$driver = new TrainDriver("Benjamin");
|
||||
$train->setDriver($driver);
|
||||
|
||||
$this->_em->persist($train);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$train = $this->_em->find(get_class($train), $train->id);
|
||||
$this->assertEquals(
|
||||
"SELECT t0.id AS id1, t0.driver_id AS driver_id2, t3.id AS id4, t3.name AS name5, t0.owner_id AS owner_id6, t7.id AS id8, t7.name AS name9 FROM Train t0 LEFT JOIN TrainDriver t3 ON t0.driver_id = t3.id INNER JOIN TrainOwner t7 ON t0.owner_id = t7.id WHERE t0.id = ?",
|
||||
$this->_sqlLoggerStack->queries[$this->_sqlLoggerStack->currentQuery]['sql']
|
||||
);
|
||||
|
||||
$this->_em->clear();
|
||||
$driver = $this->_em->find(get_class($driver), $driver->id);
|
||||
$this->assertEquals(
|
||||
"SELECT t0.id AS id1, t0.name AS name2, t3.id AS id4, t3.driver_id AS driver_id5, t3.owner_id AS owner_id6 FROM TrainOwner t0 LEFT JOIN Train t3 ON t3.owner_id = t0.id WHERE t0.id IN (?)",
|
||||
$this->_sqlLoggerStack->queries[$this->_sqlLoggerStack->currentQuery]['sql']
|
||||
);
|
||||
}
|
||||
|
||||
public function testEagerLoadWithNonNullableColumnsGeneratesInnerJoinOnOwningSide()
|
||||
{
|
||||
$waggon = new Waggon();
|
||||
$this->_em->persist($waggon);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$waggon = $this->_em->find(get_class($waggon), $waggon->id);
|
||||
$this->assertEquals(
|
||||
"SELECT t0.id AS id1, t0.train_id AS train_id2, t3.id AS id4, t3.driver_id AS driver_id5, t3.owner_id AS owner_id6 FROM Waggon t0 INNER JOIN Train t3 ON t0.train_id = t3.id WHERE t0.id = ?",
|
||||
$this->_sqlLoggerStack->queries[$this->_sqlLoggerStack->currentQuery]['sql']
|
||||
);
|
||||
}
|
||||
|
||||
public function testEagerLoadWithNonNullableColumnsGeneratesLeftJoinOnNonOwningSide()
|
||||
{
|
||||
$owner = new TrainOwner('Alexander');
|
||||
$train = new Train($owner);
|
||||
$this->_em->persist($train);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$waggon = $this->_em->find(get_class($owner), $owner->id);
|
||||
$this->assertEquals(
|
||||
"SELECT t0.id AS id1, t0.name AS name2, t3.id AS id4, t3.driver_id AS driver_id5, t3.owner_id AS owner_id6 FROM TrainOwner t0 LEFT JOIN Train t3 ON t3.owner_id = t0.id WHERE t0.id = ?",
|
||||
$this->_sqlLoggerStack->queries[$this->_sqlLoggerStack->currentQuery]['sql']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,16 +183,23 @@ class Train
|
||||
/**
|
||||
* Owning side
|
||||
* @OneToOne(targetEntity="TrainDriver", inversedBy="train", fetch="EAGER", cascade={"persist"})
|
||||
* @JoinColumn(nullable=true)
|
||||
*/
|
||||
public $driver;
|
||||
/**
|
||||
* Owning side
|
||||
* @OneToOne(targetEntity="TrainOwner", inversedBy="train", fetch="EAGER", cascade={"persist"})
|
||||
*/
|
||||
public $owner;
|
||||
/**
|
||||
* @oneToMany(targetEntity="Waggon", mappedBy="train", cascade={"persist"})
|
||||
*/
|
||||
public $waggons;
|
||||
|
||||
public function __construct()
|
||||
public function __construct(TrainOwner $owner)
|
||||
{
|
||||
$this->waggons = new \Doctrine\Common\Collections\ArrayCollection();
|
||||
$this->setOwner($owner);
|
||||
}
|
||||
|
||||
public function setDriver(TrainDriver $driver)
|
||||
@ -148,6 +208,12 @@ class Train
|
||||
$driver->setTrain($this);
|
||||
}
|
||||
|
||||
public function setOwner(TrainOwner $owner)
|
||||
{
|
||||
$this->owner = $owner;
|
||||
$owner->setTrain($this);
|
||||
}
|
||||
|
||||
public function addWaggon(Waggon $w)
|
||||
{
|
||||
$w->setTrain($this);
|
||||
@ -181,6 +247,32 @@ class TrainDriver
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class TrainOwner
|
||||
{
|
||||
/** @Id @Column(type="integer") @GeneratedValue */
|
||||
public $id;
|
||||
/** @column(type="string") */
|
||||
public $name;
|
||||
/**
|
||||
* Inverse side
|
||||
* @OneToOne(targetEntity="Train", mappedBy="owner", fetch="EAGER")
|
||||
*/
|
||||
public $train;
|
||||
|
||||
public function __construct($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function setTrain(Train $t)
|
||||
{
|
||||
$this->train = $t;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
@ -195,4 +287,4 @@ class Waggon
|
||||
{
|
||||
$this->train = $train;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,14 +27,14 @@ class ReadOnlyTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->_em->flush();
|
||||
|
||||
$readOnly->name = "Test2";
|
||||
$readOnly->number = 4321;
|
||||
$readOnly->numericValue = 4321;
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$dbReadOnly = $this->_em->find('Doctrine\Tests\ORM\Functional\ReadOnlyEntity', $readOnly->id);
|
||||
$this->assertEquals("Test1", $dbReadOnly->name);
|
||||
$this->assertEquals(1234, $dbReadOnly->number);
|
||||
$this->assertEquals(1234, $dbReadOnly->numericValue);
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,11 +51,11 @@ class ReadOnlyEntity
|
||||
/** @column(type="string") */
|
||||
public $name;
|
||||
/** @Column(type="integer") */
|
||||
public $number;
|
||||
public $numericValue;
|
||||
|
||||
public function __construct($name, $number)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->number = $number;
|
||||
$this->numericValue = $number;
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ namespace Doctrine\Tests\ORM\Functional;
|
||||
use Doctrine\ORM\Proxy\ProxyFactory;
|
||||
use Doctrine\ORM\Proxy\ProxyClassGenerator;
|
||||
use Doctrine\Tests\Models\ECommerce\ECommerceProduct;
|
||||
use Doctrine\Tests\Models\ECommerce\ECommerceShipping;
|
||||
|
||||
require_once __DIR__ . '/../../TestInit.php';
|
||||
|
||||
@ -97,7 +98,7 @@ class ReferenceProxyTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertTrue($clone->isCloned);
|
||||
$this->assertFalse($entity->isCloned);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-733
|
||||
*/
|
||||
@ -107,12 +108,12 @@ class ReferenceProxyTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
/* @var $entity Doctrine\Tests\Models\ECommerce\ECommerceProduct */
|
||||
$entity = $this->_em->getReference('Doctrine\Tests\Models\ECommerce\ECommerceProduct' , $id);
|
||||
|
||||
|
||||
$this->assertFalse($entity->__isInitialized__, "Pre-Condition: Object is unitialized proxy.");
|
||||
$this->_em->getUnitOfWork()->initializeObject($entity);
|
||||
$this->assertTrue($entity->__isInitialized__, "Should be initialized after called UnitOfWork::initializeObject()");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1163
|
||||
*/
|
||||
@ -123,10 +124,10 @@ class ReferenceProxyTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
/* @var $entity Doctrine\Tests\Models\ECommerce\ECommerceProduct */
|
||||
$entity = $this->_em->getReference('Doctrine\Tests\Models\ECommerce\ECommerceProduct' , $id);
|
||||
$entity->setName('Doctrine 2 Cookbook');
|
||||
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
$entity = $this->_em->getReference('Doctrine\Tests\Models\ECommerce\ECommerceProduct' , $id);
|
||||
$this->assertEquals('Doctrine 2 Cookbook', $entity->getName());
|
||||
}
|
||||
@ -160,6 +161,29 @@ class ReferenceProxyTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertFalse($entity->__isInitialized__, "Getting the identifier doesn't initialize the proxy.");
|
||||
}
|
||||
|
||||
public function testDoNotInitializeProxyOnGettingTheIdentifierAndReturnTheRightType()
|
||||
{
|
||||
$product = new ECommerceProduct();
|
||||
$product->setName('Doctrine Cookbook');
|
||||
|
||||
$shipping = new ECommerceShipping();
|
||||
$shipping->setDays(1);
|
||||
$product->setShipping($shipping);
|
||||
$this->_em->persist($product);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$id = $shipping->getId();
|
||||
|
||||
$product = $this->_em->getRepository('Doctrine\Tests\Models\ECommerce\ECommerceProduct')->find($product->getId());
|
||||
|
||||
$entity = $product->getShipping();
|
||||
$this->assertFalse($entity->__isInitialized__, "Pre-Condition: Object is unitialized proxy.");
|
||||
$this->assertEquals($id, $entity->getId());
|
||||
$this->assertSame($id, $entity->getId(), "Check that the id's are the same value, and type.");
|
||||
$this->assertFalse($entity->__isInitialized__, "Getting the identifier doesn't initialize the proxy.");
|
||||
}
|
||||
|
||||
public function testInitializeProxyOnGettingSomethingOtherThanTheIdentifier()
|
||||
{
|
||||
$id = $this->createProduct();
|
||||
|
@ -21,7 +21,7 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$address = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress');
|
||||
$this->assertEquals(1, $address->sequenceGeneratorDefinition['allocationSize']);
|
||||
}
|
||||
|
||||
|
||||
public function testGetCreateSchemaSql()
|
||||
{
|
||||
$classes = array(
|
||||
@ -32,26 +32,30 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$tool = new SchemaTool($this->_em);
|
||||
$sql = $tool->getCreateSchemaSql($classes);
|
||||
|
||||
$this->assertEquals("CREATE TABLE cms_addresses (id INT NOT NULL, user_id INT DEFAULT NULL, country VARCHAR(50) NOT NULL, zip VARCHAR(50) NOT NULL, city VARCHAR(50) NOT NULL, PRIMARY KEY(id))", $sql[0]);
|
||||
$this->assertEquals("CREATE UNIQUE INDEX UNIQ_ACAC157BA76ED395 ON cms_addresses (user_id)", $sql[1]);
|
||||
$this->assertEquals("CREATE TABLE cms_users (id INT NOT NULL, status VARCHAR(50) NOT NULL, username VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))", $sql[2]);
|
||||
$this->assertEquals("CREATE UNIQUE INDEX UNIQ_3AF03EC5F85E0677 ON cms_users (username)", $sql[3]);
|
||||
$this->assertEquals("CREATE TABLE cms_users_groups (user_id INT NOT NULL, group_id INT NOT NULL, PRIMARY KEY(user_id, group_id))", $sql[4]);
|
||||
$this->assertEquals("CREATE INDEX IDX_7EA9409AA76ED395 ON cms_users_groups (user_id)", $sql[5]);
|
||||
$this->assertEquals("CREATE INDEX IDX_7EA9409AFE54D947 ON cms_users_groups (group_id)", $sql[6]);
|
||||
$this->assertEquals("CREATE TABLE cms_phonenumbers (phonenumber VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, PRIMARY KEY(phonenumber))", $sql[7]);
|
||||
$this->assertEquals("CREATE INDEX IDX_F21F790FA76ED395 ON cms_phonenumbers (user_id)", $sql[8]);
|
||||
$this->assertEquals("CREATE SEQUENCE cms_addresses_id_seq INCREMENT BY 1 MINVALUE 1 START 1", $sql[9]);
|
||||
$this->assertEquals("CREATE SEQUENCE cms_users_id_seq INCREMENT BY 1 MINVALUE 1 START 1", $sql[10]);
|
||||
$this->assertEquals("ALTER TABLE cms_addresses ADD FOREIGN KEY (user_id) REFERENCES cms_users(id) NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[11]);
|
||||
$this->assertEquals("ALTER TABLE cms_users_groups ADD FOREIGN KEY (user_id) REFERENCES cms_users(id) NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[12]);
|
||||
$this->assertEquals("ALTER TABLE cms_users_groups ADD FOREIGN KEY (group_id) REFERENCES cms_groups(id) NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[13]);
|
||||
$this->assertEquals("ALTER TABLE cms_phonenumbers ADD FOREIGN KEY (user_id) REFERENCES cms_users(id) NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[14]);
|
||||
|
||||
$this->assertEquals(count($sql), 15);
|
||||
$sqlCount = count($sql);
|
||||
|
||||
$this->assertEquals("CREATE TABLE cms_addresses (id INT NOT NULL, user_id INT DEFAULT NULL, country VARCHAR(50) NOT NULL, zip VARCHAR(50) NOT NULL, city VARCHAR(50) NOT NULL, PRIMARY KEY(id))", array_shift($sql));
|
||||
$this->assertEquals("CREATE UNIQUE INDEX UNIQ_ACAC157BA76ED395 ON cms_addresses (user_id)", array_shift($sql));
|
||||
$this->assertEquals("CREATE TABLE cms_users (id INT NOT NULL, email_id INT DEFAULT NULL, status VARCHAR(50) DEFAULT NULL, username VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))", array_shift($sql));
|
||||
$this->assertEquals("CREATE UNIQUE INDEX UNIQ_3AF03EC5F85E0677 ON cms_users (username)", array_shift($sql));
|
||||
$this->assertEquals("CREATE UNIQUE INDEX UNIQ_3AF03EC5A832C1C9 ON cms_users (email_id)", array_shift($sql));
|
||||
$this->assertEquals("CREATE TABLE cms_users_groups (user_id INT NOT NULL, group_id INT NOT NULL, PRIMARY KEY(user_id, group_id))", array_shift($sql));
|
||||
$this->assertEquals("CREATE INDEX IDX_7EA9409AA76ED395 ON cms_users_groups (user_id)", array_shift($sql));
|
||||
$this->assertEquals("CREATE INDEX IDX_7EA9409AFE54D947 ON cms_users_groups (group_id)", array_shift($sql));
|
||||
$this->assertEquals("CREATE TABLE cms_phonenumbers (phonenumber VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, PRIMARY KEY(phonenumber))", array_shift($sql));
|
||||
$this->assertEquals("CREATE INDEX IDX_F21F790FA76ED395 ON cms_phonenumbers (user_id)", array_shift($sql));
|
||||
$this->assertEquals("CREATE SEQUENCE cms_addresses_id_seq INCREMENT BY 1 MINVALUE 1 START 1", array_shift($sql));
|
||||
$this->assertEquals("CREATE SEQUENCE cms_users_id_seq INCREMENT BY 1 MINVALUE 1 START 1", array_shift($sql));
|
||||
$this->assertEquals("ALTER TABLE cms_addresses ADD CONSTRAINT FK_ACAC157BA76ED395 FOREIGN KEY (user_id) REFERENCES cms_users (id) NOT DEFERRABLE INITIALLY IMMEDIATE", array_shift($sql));
|
||||
$this->assertEquals("ALTER TABLE cms_users ADD CONSTRAINT FK_3AF03EC5A832C1C9 FOREIGN KEY (email_id) REFERENCES cms_emails (id) NOT DEFERRABLE INITIALLY IMMEDIATE", array_shift($sql));
|
||||
$this->assertEquals("ALTER TABLE cms_users_groups ADD CONSTRAINT FK_7EA9409AA76ED395 FOREIGN KEY (user_id) REFERENCES cms_users (id) NOT DEFERRABLE INITIALLY IMMEDIATE", array_shift($sql));
|
||||
$this->assertEquals("ALTER TABLE cms_users_groups ADD CONSTRAINT FK_7EA9409AFE54D947 FOREIGN KEY (group_id) REFERENCES cms_groups (id) NOT DEFERRABLE INITIALLY IMMEDIATE", array_shift($sql));
|
||||
$this->assertEquals("ALTER TABLE cms_phonenumbers ADD CONSTRAINT FK_F21F790FA76ED395 FOREIGN KEY (user_id) REFERENCES cms_users (id) NOT DEFERRABLE INITIALLY IMMEDIATE", array_shift($sql));
|
||||
|
||||
$this->assertEquals(array(), $sql, "SQL Array should be empty now.");
|
||||
$this->assertEquals(17, $sqlCount, "Total of 17 queries should be executed");
|
||||
}
|
||||
|
||||
|
||||
public function testGetCreateSchemaSql2()
|
||||
{
|
||||
$classes = array(
|
||||
@ -62,11 +66,11 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$sql = $tool->getCreateSchemaSql($classes);
|
||||
|
||||
$this->assertEquals(2, count($sql));
|
||||
|
||||
|
||||
$this->assertEquals('CREATE TABLE decimal_model (id INT NOT NULL, "decimal" NUMERIC(5, 2) NOT NULL, "high_scale" NUMERIC(14, 4) NOT NULL, PRIMARY KEY(id))', $sql[0]);
|
||||
$this->assertEquals("CREATE SEQUENCE decimal_model_id_seq INCREMENT BY 1 MINVALUE 1 START 1", $sql[1]);
|
||||
}
|
||||
|
||||
|
||||
public function testGetCreateSchemaSql3()
|
||||
{
|
||||
$classes = array(
|
||||
@ -75,12 +79,12 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$tool = new SchemaTool($this->_em);
|
||||
$sql = $tool->getCreateSchemaSql($classes);
|
||||
|
||||
|
||||
$this->assertEquals(2, count($sql));
|
||||
$this->assertEquals("CREATE TABLE boolean_model (id INT NOT NULL, booleanField BOOLEAN NOT NULL, PRIMARY KEY(id))", $sql[0]);
|
||||
$this->assertEquals("CREATE SEQUENCE boolean_model_id_seq INCREMENT BY 1 MINVALUE 1 START 1", $sql[1]);
|
||||
}
|
||||
|
||||
|
||||
public function testGetDropSchemaSql()
|
||||
{
|
||||
$classes = array(
|
||||
@ -91,8 +95,8 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$tool = new SchemaTool($this->_em);
|
||||
$sql = $tool->getDropSchemaSQL($classes);
|
||||
|
||||
$this->assertEquals(13, count($sql));
|
||||
|
||||
$this->assertEquals(14, count($sql));
|
||||
$dropSequenceSQLs = 0;
|
||||
foreach ($sql AS $stmt) {
|
||||
if (strpos($stmt, "DROP SEQUENCE") === 0) {
|
||||
|
@ -24,7 +24,7 @@ class DDC1040Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$user->name = "John Galt";
|
||||
$user->username = "jgalt";
|
||||
$user->status = "inactive";
|
||||
|
||||
|
||||
$article = new CmsArticle();
|
||||
$article->topic = "This is John Galt speaking!";
|
||||
$article->text = "Yadda Yadda!";
|
||||
@ -44,11 +44,10 @@ class DDC1040Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
->setParameter('author', $user)
|
||||
->getResult();
|
||||
|
||||
$dql = "SELECT a FROM Doctrine\Tests\Models\CMS\CmsArticle a WHERE a.topic = :topic AND a.user = :author AND a.user = :author AND a.text = :text";
|
||||
$dql = "SELECT a FROM Doctrine\Tests\Models\CMS\CmsArticle a WHERE a.topic = :topic AND a.user = :author AND a.user = :author";
|
||||
$farticle = $this->_em->createQuery($dql)
|
||||
->setParameter('author', $user)
|
||||
->setParameter('topic', 'This is John Galt speaking!')
|
||||
->setParameter('text', 'Yadda Yadda!')
|
||||
->getSingleResult();
|
||||
|
||||
$this->assertSame($article, $farticle);
|
||||
@ -70,12 +69,11 @@ class DDC1040Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->_em->persist($article);
|
||||
$this->_em->flush();
|
||||
|
||||
$dql = "SELECT a FROM Doctrine\Tests\Models\CMS\CmsArticle a WHERE a.topic = ?1 AND a.user = ?2 AND a.user = ?3 AND a.text = ?4";
|
||||
$dql = "SELECT a FROM Doctrine\Tests\Models\CMS\CmsArticle a WHERE a.topic = ?1 AND a.user = ?2 AND a.user = ?3";
|
||||
$farticle = $this->_em->createQuery($dql)
|
||||
->setParameter(1, 'This is John Galt speaking!')
|
||||
->setParameter(2, $user)
|
||||
->setParameter(3, $user)
|
||||
->setParameter(4, 'Yadda Yadda!')
|
||||
->getSingleResult();
|
||||
|
||||
$this->assertSame($article, $farticle);
|
||||
|
@ -8,18 +8,18 @@ require_once __DIR__ . '/../../../TestInit.php';
|
||||
* @group DDC-1151
|
||||
*/
|
||||
class DDC1151Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
{
|
||||
public function testQuoteForeignKey()
|
||||
{
|
||||
if ($this->_em->getConnection()->getDatabasePlatform()->getName() != 'postgresql') {
|
||||
$this->markTestSkipped("This test is useful for all databases, but designed only for postgresql.");
|
||||
}
|
||||
|
||||
|
||||
$sql = $this->_schemaTool->getCreateSchemaSql(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1151User'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1151Group'),
|
||||
));
|
||||
|
||||
|
||||
$this->assertEquals("CREATE TABLE \"User\" (id INT NOT NULL, PRIMARY KEY(id))", $sql[0]);
|
||||
$this->assertEquals("CREATE TABLE ddc1151user_ddc1151group (ddc1151user_id INT NOT NULL, ddc1151group_id INT NOT NULL, PRIMARY KEY(ddc1151user_id, ddc1151group_id))", $sql[1]);
|
||||
$this->assertEquals("CREATE INDEX IDX_88A3259AC5AD08A ON ddc1151user_ddc1151group (ddc1151user_id)", $sql[2]);
|
||||
@ -27,8 +27,8 @@ class DDC1151Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertEquals("CREATE TABLE \"Group\" (id INT NOT NULL, PRIMARY KEY(id))", $sql[4]);
|
||||
$this->assertEquals("CREATE SEQUENCE User_id_seq INCREMENT BY 1 MINVALUE 1 START 1", $sql[5]);
|
||||
$this->assertEquals("CREATE SEQUENCE Group_id_seq INCREMENT BY 1 MINVALUE 1 START 1", $sql[6]);
|
||||
$this->assertEquals("ALTER TABLE ddc1151user_ddc1151group ADD FOREIGN KEY (ddc1151user_id) REFERENCES \"User\"(id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[7]);
|
||||
$this->assertEquals("ALTER TABLE ddc1151user_ddc1151group ADD FOREIGN KEY (ddc1151group_id) REFERENCES \"Group\"(id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[8]);
|
||||
$this->assertEquals("ALTER TABLE ddc1151user_ddc1151group ADD CONSTRAINT FK_88A3259AC5AD08A FOREIGN KEY (ddc1151user_id) REFERENCES \"User\" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[7]);
|
||||
$this->assertEquals("ALTER TABLE ddc1151user_ddc1151group ADD CONSTRAINT FK_88A32597357E0B1 FOREIGN KEY (ddc1151group_id) REFERENCES \"Group\" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[8]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ class DDC1151User
|
||||
{
|
||||
/** @Id @Column(type="integer") @GeneratedValue */
|
||||
public $id;
|
||||
|
||||
|
||||
/** @ManyToMany(targetEntity="DDC1151Group") */
|
||||
public $groups;
|
||||
}
|
||||
|
@ -209,8 +209,15 @@ class DDC117Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->article1->addTranslation('en', 'Bar');
|
||||
$this->article1->addTranslation('en', 'Baz');
|
||||
|
||||
$this->setExpectedException('Exception');
|
||||
$this->_em->flush();
|
||||
$exceptionThrown = false;
|
||||
try {
|
||||
// exception depending on the underyling Database Driver
|
||||
$this->_em->flush();
|
||||
} catch(\Exception $e) {
|
||||
$exceptionThrown = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($exceptionThrown, "The underlying database driver throws an exception.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -106,7 +106,7 @@ class DDC1209_3
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @Column(type="datetime")
|
||||
* @Column(type="datetime", name="somedate")
|
||||
*/
|
||||
private $date;
|
||||
|
||||
|
@ -21,10 +21,10 @@ class DDC1225Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1225_TestEntity2'),
|
||||
));
|
||||
} catch(\PDOException $e) {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function testIssue()
|
||||
{
|
||||
$qb = $this->_em->createQueryBuilder();
|
||||
@ -32,10 +32,10 @@ class DDC1225Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
->select('te1')
|
||||
->where('te1.testEntity2 = ?1')
|
||||
->setParameter(1, 0);
|
||||
|
||||
|
||||
$this->assertEquals(
|
||||
'SELECT t0_.test_entity2_id AS test_entity2_id0 FROM te1 t0_ WHERE t0_.test_entity2_id = ?',
|
||||
$qb->getQuery()->getSQL()
|
||||
strtolower('SELECT t0_.test_entity2_id AS test_entity2_id0 FROM te1 t0_ WHERE t0_.test_entity2_id = ?'),
|
||||
strtolower($qb->getQuery()->getSQL())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -21,58 +21,58 @@ class DDC1228Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1228User'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1228Profile'),
|
||||
));
|
||||
} catch(\PDOException $e) {
|
||||
|
||||
} catch(\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function testOneToOnePersist()
|
||||
{
|
||||
$user = new DDC1228User;
|
||||
$profile = new DDC1228Profile();
|
||||
$profile->name = "Foo";
|
||||
$user->profile = $profile;
|
||||
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->persist($profile);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
$user = $this->_em->find(__NAMESPACE__ . '\\DDC1228User', $user->id);
|
||||
|
||||
|
||||
$this->assertFalse($user->getProfile()->__isInitialized__, "Proxy is not initialized");
|
||||
$user->getProfile()->setName("Bar");
|
||||
$this->assertTrue($user->getProfile()->__isInitialized__, "Proxy is not initialized");
|
||||
|
||||
|
||||
$this->assertEquals("Bar", $user->getProfile()->getName());
|
||||
$this->assertEquals(array("id" => 1, "name" => "Foo"), $this->_em->getUnitOfWork()->getOriginalEntityData($user->getProfile()));
|
||||
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
$user = $this->_em->find(__NAMESPACE__ . '\\DDC1228User', $user->id);
|
||||
$this->assertEquals("Bar", $user->getProfile()->getName());
|
||||
}
|
||||
|
||||
|
||||
public function testRefresh()
|
||||
{
|
||||
$user = new DDC1228User;
|
||||
$profile = new DDC1228Profile();
|
||||
$profile->name = "Foo";
|
||||
$user->profile = $profile;
|
||||
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->persist($profile);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
$user = $this->_em->getReference(__NAMESPACE__ . '\\DDC1228User', $user->id);
|
||||
|
||||
|
||||
$this->_em->refresh($user);
|
||||
$user->name = "Baz";
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
$user = $this->_em->find(__NAMESPACE__ . '\\DDC1228User', $user->id);
|
||||
$this->assertEquals("Baz", $user->name);
|
||||
}
|
||||
@ -88,20 +88,20 @@ class DDC1228User
|
||||
* @var int
|
||||
*/
|
||||
public $id;
|
||||
|
||||
|
||||
/**
|
||||
* @column(type="string")
|
||||
* @Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
public $name = '';
|
||||
|
||||
public $name = 'Bar';
|
||||
|
||||
/**
|
||||
* @OneToOne(targetEntity="DDC1228Profile")
|
||||
* @var Profile
|
||||
*/
|
||||
public $profile;
|
||||
|
||||
public function getProfile()
|
||||
|
||||
public function getProfile()
|
||||
{
|
||||
return $this->profile;
|
||||
}
|
||||
@ -117,13 +117,13 @@ class DDC1228Profile
|
||||
* @var int
|
||||
*/
|
||||
public $id;
|
||||
|
||||
|
||||
/**
|
||||
* @column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
|
@ -19,49 +19,49 @@ class DDC1238Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1238User'),
|
||||
));
|
||||
} catch(\PDOException $e) {
|
||||
|
||||
} catch(\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function testIssue()
|
||||
{
|
||||
$user = new DDC1238User;
|
||||
$user->setName("test");
|
||||
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
$userId = $user->getId();
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
$user = $this->_em->getReference(__NAMESPACE__ . '\\DDC1238User', $userId);
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
$userId2 = $user->getId();
|
||||
$this->assertEquals($userId, $userId2, "This proxy can still be initialized.");
|
||||
}
|
||||
|
||||
|
||||
public function testIssueProxyClear()
|
||||
{
|
||||
$user = new DDC1238User;
|
||||
$user->setName("test");
|
||||
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
// force proxy load, getId() doesn't work anymore
|
||||
$user->getName();
|
||||
$userId = $user->getId();
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
$user = $this->_em->getReference(__NAMESPACE__ . '\\DDC1238User', $userId);
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
$user2 = $this->_em->getReference(__NAMESPACE__ . '\\DDC1238User', $userId);
|
||||
|
||||
|
||||
// force proxy load, getId() doesn't work anymore
|
||||
$user->getName();
|
||||
$this->assertNull($user->getId(), "Now this is null, we already have a user instance of that type");
|
||||
@ -75,18 +75,18 @@ class DDC1238User
|
||||
{
|
||||
/** @Id @GeneratedValue @Column(type="integer") */
|
||||
private $id;
|
||||
|
||||
|
||||
/**
|
||||
* @Column
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
|
@ -7,56 +7,56 @@ use DateTime;
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
/**
|
||||
* @group DDC-1135
|
||||
* @group DDC-1335
|
||||
*/
|
||||
class DDC1135Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
class DDC1335Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
try {
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1135User'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1135Phone'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1335User'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1335Phone'),
|
||||
));
|
||||
$this->loadFixture();
|
||||
} catch(\Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public function testDql()
|
||||
{
|
||||
$dql = 'SELECT u FROM ' . __NAMESPACE__ . '\DDC1135User u INDEX BY u.id';
|
||||
$dql = 'SELECT u FROM ' . __NAMESPACE__ . '\DDC1335User u INDEX BY u.id';
|
||||
$query = $this->_em->createQuery($dql);
|
||||
$result = $query->getResult();
|
||||
|
||||
|
||||
$this->assertEquals(sizeof($result), 3);
|
||||
$this->assertArrayHasKey(1, $result);
|
||||
$this->assertArrayHasKey(2, $result);
|
||||
$this->assertArrayHasKey(3, $result);
|
||||
|
||||
$dql = 'SELECT u, p FROM '.__NAMESPACE__ . '\DDC1135User u INDEX BY u.email INNER JOIN u.phones p INDEX BY p.id';
|
||||
|
||||
$dql = 'SELECT u, p FROM '.__NAMESPACE__ . '\DDC1335User u INDEX BY u.email INNER JOIN u.phones p INDEX BY p.id';
|
||||
$query = $this->_em->createQuery($dql);
|
||||
$result = $query->getResult();
|
||||
|
||||
|
||||
$this->assertEquals(sizeof($result), 3);
|
||||
$this->assertArrayHasKey('foo@foo.com', $result);
|
||||
$this->assertArrayHasKey('bar@bar.com', $result);
|
||||
$this->assertArrayHasKey('foobar@foobar.com', $result);
|
||||
|
||||
|
||||
$this->assertEquals(sizeof($result['foo@foo.com']->phones), 3);
|
||||
$this->assertEquals(sizeof($result['bar@bar.com']->phones), 3);
|
||||
$this->assertEquals(sizeof($result['foobar@foobar.com']->phones), 3);
|
||||
|
||||
|
||||
$this->assertArrayHasKey(1, $result['foo@foo.com']->phones->toArray());
|
||||
$this->assertArrayHasKey(2, $result['foo@foo.com']->phones->toArray());
|
||||
$this->assertArrayHasKey(3, $result['foo@foo.com']->phones->toArray());
|
||||
|
||||
|
||||
$this->assertArrayHasKey(4, $result['bar@bar.com']->phones->toArray());
|
||||
$this->assertArrayHasKey(5, $result['bar@bar.com']->phones->toArray());
|
||||
$this->assertArrayHasKey(6, $result['bar@bar.com']->phones->toArray());
|
||||
|
||||
|
||||
$this->assertArrayHasKey(7, $result['foobar@foobar.com']->phones->toArray());
|
||||
$this->assertArrayHasKey(8, $result['foobar@foobar.com']->phones->toArray());
|
||||
$this->assertArrayHasKey(9, $result['foobar@foobar.com']->phones->toArray());
|
||||
@ -65,77 +65,77 @@ class DDC1135Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
public function testTicket()
|
||||
{
|
||||
$builder = $this->_em->createQueryBuilder();
|
||||
$builder->select('u')->from(__NAMESPACE__ . '\DDC1135User', 'u', 'u.id');
|
||||
$builder->select('u')->from(__NAMESPACE__ . '\DDC1335User', 'u', 'u.id');
|
||||
|
||||
$dql = $builder->getQuery()->getDQL();
|
||||
$result = $builder->getQuery()->getResult();
|
||||
|
||||
|
||||
$this->assertEquals(sizeof($result), 3);
|
||||
$this->assertArrayHasKey(1, $result);
|
||||
$this->assertArrayHasKey(2, $result);
|
||||
$this->assertArrayHasKey(3, $result);
|
||||
$this->assertEquals('SELECT u FROM ' . __NAMESPACE__ . '\DDC1135User u INDEX BY u.id', $dql);
|
||||
$this->assertEquals('SELECT u FROM ' . __NAMESPACE__ . '\DDC1335User u INDEX BY u.id', $dql);
|
||||
}
|
||||
|
||||
|
||||
public function testIndexByUnique()
|
||||
{
|
||||
$builder = $this->_em->createQueryBuilder();
|
||||
$builder->select('u')->from(__NAMESPACE__ . '\DDC1135User', 'u', 'u.email');
|
||||
$builder->select('u')->from(__NAMESPACE__ . '\DDC1335User', 'u', 'u.email');
|
||||
|
||||
$dql = $builder->getQuery()->getDQL();
|
||||
$result = $builder->getQuery()->getResult();
|
||||
|
||||
|
||||
$this->assertEquals(sizeof($result), 3);
|
||||
$this->assertArrayHasKey('foo@foo.com', $result);
|
||||
$this->assertArrayHasKey('bar@bar.com', $result);
|
||||
$this->assertArrayHasKey('foobar@foobar.com', $result);
|
||||
$this->assertEquals('SELECT u FROM ' . __NAMESPACE__ . '\DDC1135User u INDEX BY u.email', $dql);
|
||||
$this->assertEquals('SELECT u FROM ' . __NAMESPACE__ . '\DDC1335User u INDEX BY u.email', $dql);
|
||||
}
|
||||
|
||||
|
||||
public function testIndexWithJoin()
|
||||
{
|
||||
$builder = $this->_em->createQueryBuilder();
|
||||
$builder->select('u','p')
|
||||
->from(__NAMESPACE__ . '\DDC1135User', 'u', 'u.email')
|
||||
->from(__NAMESPACE__ . '\DDC1335User', 'u', 'u.email')
|
||||
->join('u.phones', 'p', null, null, 'p.id');
|
||||
|
||||
|
||||
$dql = $builder->getQuery()->getDQL();
|
||||
$result = $builder->getQuery()->getResult();
|
||||
|
||||
|
||||
$this->assertEquals(sizeof($result), 3);
|
||||
$this->assertArrayHasKey('foo@foo.com', $result);
|
||||
$this->assertArrayHasKey('bar@bar.com', $result);
|
||||
$this->assertArrayHasKey('foobar@foobar.com', $result);
|
||||
|
||||
|
||||
$this->assertEquals(sizeof($result['foo@foo.com']->phones), 3);
|
||||
$this->assertEquals(sizeof($result['bar@bar.com']->phones), 3);
|
||||
$this->assertEquals(sizeof($result['foobar@foobar.com']->phones), 3);
|
||||
|
||||
|
||||
$this->assertArrayHasKey(1, $result['foo@foo.com']->phones->toArray());
|
||||
$this->assertArrayHasKey(2, $result['foo@foo.com']->phones->toArray());
|
||||
$this->assertArrayHasKey(3, $result['foo@foo.com']->phones->toArray());
|
||||
|
||||
|
||||
$this->assertArrayHasKey(4, $result['bar@bar.com']->phones->toArray());
|
||||
$this->assertArrayHasKey(5, $result['bar@bar.com']->phones->toArray());
|
||||
$this->assertArrayHasKey(6, $result['bar@bar.com']->phones->toArray());
|
||||
|
||||
|
||||
$this->assertArrayHasKey(7, $result['foobar@foobar.com']->phones->toArray());
|
||||
$this->assertArrayHasKey(8, $result['foobar@foobar.com']->phones->toArray());
|
||||
$this->assertArrayHasKey(9, $result['foobar@foobar.com']->phones->toArray());
|
||||
|
||||
$this->assertEquals('SELECT u, p FROM '.__NAMESPACE__ . '\DDC1135User u INDEX BY u.email INNER JOIN u.phones p INDEX BY p.id', $dql);
|
||||
|
||||
$this->assertEquals('SELECT u, p FROM '.__NAMESPACE__ . '\DDC1335User u INDEX BY u.email INNER JOIN u.phones p INDEX BY p.id', $dql);
|
||||
}
|
||||
|
||||
|
||||
private function loadFixture()
|
||||
{
|
||||
$p1 = array('11 xxxx-xxxx','11 yyyy-yyyy','11 zzzz-zzzz');
|
||||
$p2 = array('22 xxxx-xxxx','22 yyyy-yyyy','22 zzzz-zzzz');
|
||||
$p3 = array('33 xxxx-xxxx','33 yyyy-yyyy','33 zzzz-zzzz');
|
||||
|
||||
$u1 = new DDC1135User("foo@foo.com", "Foo",$p1);
|
||||
$u2 = new DDC1135User("bar@bar.com", "Bar",$p2);
|
||||
$u3 = new DDC1135User("foobar@foobar.com", "Foo Bar",$p3);
|
||||
|
||||
|
||||
$u1 = new DDC1335User("foo@foo.com", "Foo",$p1);
|
||||
$u2 = new DDC1335User("bar@bar.com", "Bar",$p2);
|
||||
$u3 = new DDC1335User("foobar@foobar.com", "Foo Bar",$p3);
|
||||
|
||||
$this->_em->persist($u1);
|
||||
$this->_em->persist($u2);
|
||||
$this->_em->persist($u3);
|
||||
@ -148,7 +148,7 @@ class DDC1135Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1135User
|
||||
class DDC1335User
|
||||
{
|
||||
/**
|
||||
* @Id @Column(type="integer")
|
||||
@ -160,25 +160,25 @@ class DDC1135User
|
||||
* @Column(type="string", unique=true)
|
||||
*/
|
||||
public $email;
|
||||
|
||||
|
||||
/**
|
||||
* @Column(type="string")
|
||||
*/
|
||||
public $name;
|
||||
|
||||
|
||||
/**
|
||||
* @OneToMany(targetEntity="DDC1135Phone", mappedBy="user", cascade={"persist", "remove"})
|
||||
* @OneToMany(targetEntity="DDC1335Phone", mappedBy="user", cascade={"persist", "remove"})
|
||||
*/
|
||||
public $phones;
|
||||
|
||||
|
||||
public function __construct($email, $name, array $numbers = array())
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->email = $email;
|
||||
$this->phones = new \Doctrine\Common\Collections\ArrayCollection();
|
||||
|
||||
|
||||
foreach ($numbers as $number) {
|
||||
$this->phones->add(new DDC1135Phone($this,$number));
|
||||
$this->phones->add(new DDC1335Phone($this,$number));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -186,22 +186,22 @@ class DDC1135User
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1135Phone
|
||||
class DDC1335Phone
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @Column(name="id", type="integer")
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
* @GeneratedValue
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @Column(name="number", type="string", nullable = false)
|
||||
* @Column(name="numericalValue", type="string", nullable = false)
|
||||
*/
|
||||
public $number;
|
||||
public $numericalValue;
|
||||
|
||||
/**
|
||||
* @ManyToOne(targetEntity="DDC1135User", inversedBy="phones")
|
||||
* @ManyToOne(targetEntity="DDC1335User", inversedBy="phones")
|
||||
* @JoinColumn(name="user_id", referencedColumnName="id", nullable = false)
|
||||
*/
|
||||
public $user;
|
||||
@ -209,6 +209,6 @@ class DDC1135Phone
|
||||
public function __construct($user, $number)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->number = $number;
|
||||
$this->numericalValue = $number;
|
||||
}
|
||||
}
|
129
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1404Test.php
Normal file
129
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1404Test.php
Normal file
@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
/**
|
||||
* @group DDC-1404
|
||||
*/
|
||||
class DDC1404Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
try {
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1404ParentEntity'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1404ChildEntity'),
|
||||
));
|
||||
|
||||
$this->loadFixtures();
|
||||
|
||||
} catch (Exception $exc) {
|
||||
}
|
||||
}
|
||||
|
||||
public function testTicket()
|
||||
{
|
||||
$repository = $this->_em->getRepository(__NAMESPACE__ . '\DDC1404ChildEntity');
|
||||
$queryAll = $repository->createNamedQuery('all');
|
||||
$queryFirst = $repository->createNamedQuery('first');
|
||||
$querySecond = $repository->createNamedQuery('second');
|
||||
|
||||
|
||||
$this->assertEquals('SELECT p FROM Doctrine\Tests\ORM\Functional\Ticket\DDC1404ChildEntity p', $queryAll->getDQL());
|
||||
$this->assertEquals('SELECT p FROM Doctrine\Tests\ORM\Functional\Ticket\DDC1404ChildEntity p WHERE p.id = 1', $queryFirst->getDQL());
|
||||
$this->assertEquals('SELECT p FROM Doctrine\Tests\ORM\Functional\Ticket\DDC1404ChildEntity p WHERE p.id = 2', $querySecond->getDQL());
|
||||
|
||||
|
||||
$this->assertEquals(sizeof($queryAll->getResult()), 2);
|
||||
$this->assertEquals(sizeof($queryFirst->getResult()), 1);
|
||||
$this->assertEquals(sizeof($querySecond->getResult()), 1);
|
||||
}
|
||||
|
||||
|
||||
public function loadFixtures()
|
||||
{
|
||||
$c1 = new DDC1404ChildEntity("ChildEntity 1");
|
||||
$c2 = new DDC1404ChildEntity("ChildEntity 2");
|
||||
|
||||
$this->_em->persist($c1);
|
||||
$this->_em->persist($c2);
|
||||
|
||||
$this->_em->flush();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @MappedSuperclass
|
||||
*
|
||||
* @NamedQueries({
|
||||
* @NamedQuery(name="all", query="SELECT p FROM __CLASS__ p"),
|
||||
* @NamedQuery(name="first", query="SELECT p FROM __CLASS__ p WHERE p.id = 1"),
|
||||
* })
|
||||
*/
|
||||
class DDC1404ParentEntity
|
||||
{
|
||||
|
||||
/**
|
||||
* @Id
|
||||
* @Column(type="integer")
|
||||
* @GeneratedValue()
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*
|
||||
* @NamedQueries({
|
||||
* @NamedQuery(name="first", query="SELECT p FROM __CLASS__ p WHERE p.id = 1"),
|
||||
* @NamedQuery(name="second", query="SELECT p FROM __CLASS__ p WHERE p.id = 2")
|
||||
* })
|
||||
*/
|
||||
class DDC1404ChildEntity extends DDC1404ParentEntity
|
||||
{
|
||||
|
||||
/**
|
||||
* @column(type="string")
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*/
|
||||
public function __construct($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
}
|
131
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1458Test.php
Normal file
131
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1458Test.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Tests\Models\CMS\CmsUser;
|
||||
use Doctrine\Tests\Models\CMS\CmsGroup;
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
class DDC1258Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\TestEntity'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\TestAdditionalEntity')
|
||||
));
|
||||
}
|
||||
|
||||
public function testIssue()
|
||||
{
|
||||
$testEntity = new TestEntity();
|
||||
$testEntity->setValue(3);
|
||||
$testEntity->setAdditional(new TestAdditionalEntity());
|
||||
$this->_em->persist($testEntity);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
// So here the value is 3
|
||||
$this->assertEquals(3, $testEntity->getValue());
|
||||
|
||||
$test = $this->_em->getRepository(__NAMESPACE__ . '\TestEntity')->find(1);
|
||||
|
||||
// New value is set
|
||||
$test->setValue(5);
|
||||
|
||||
// So here the value is 5
|
||||
$this->assertEquals(5, $test->getValue());
|
||||
|
||||
// Get the additional entity
|
||||
$additional = $test->getAdditional();
|
||||
|
||||
// Still 5..
|
||||
$this->assertEquals(5, $test->getValue());
|
||||
|
||||
// Force the proxy to load
|
||||
$additional->getBool();
|
||||
|
||||
// The value should still be 5
|
||||
$this->assertEquals(5, $test->getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class TestEntity
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @Column(type="integer")
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
protected $id;
|
||||
/**
|
||||
* @Column(type="integer")
|
||||
*/
|
||||
protected $value;
|
||||
/**
|
||||
* @OneToOne(targetEntity="TestAdditionalEntity", inversedBy="entity", orphanRemoval=true, cascade={"persist", "remove"})
|
||||
*/
|
||||
protected $additional;
|
||||
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
public function setValue($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function getAdditional()
|
||||
{
|
||||
return $this->additional;
|
||||
}
|
||||
|
||||
public function setAdditional($additional)
|
||||
{
|
||||
$this->additional = $additional;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class TestAdditionalEntity
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @Column(type="integer")
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
protected $id;
|
||||
/**
|
||||
* @OneToOne(targetEntity="TestEntity", mappedBy="additional")
|
||||
*/
|
||||
protected $entity;
|
||||
/**
|
||||
* @Column(type="boolean")
|
||||
*/
|
||||
protected $bool;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->bool = false;
|
||||
}
|
||||
|
||||
public function getBool()
|
||||
{
|
||||
return $this->bool;
|
||||
}
|
||||
|
||||
public function setBool($bool)
|
||||
{
|
||||
$this->bool = $bool;
|
||||
}
|
||||
}
|
86
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1461Test.php
Normal file
86
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1461Test.php
Normal file
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Tests\Models\CMS\CmsArticle;
|
||||
use Doctrine\Tests\Models\CMS\CmsUser;
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
/**
|
||||
* @group DDC-1461
|
||||
*/
|
||||
class DDC1461Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
try {
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1461TwitterAccount'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1461User')
|
||||
));
|
||||
} catch(\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function testChangeDetectionDeferredExplicit()
|
||||
{
|
||||
$user = new DDC1461User;
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_MANAGED, $this->_em->getUnitOfWork()->getEntityState($user, \Doctrine\ORM\UnitOfWork::STATE_NEW), "Entity should be managed.");
|
||||
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_MANAGED, $this->_em->getUnitOfWork()->getEntityState($user), "Entity should be managed.");
|
||||
|
||||
$acc = new DDC1461TwitterAccount;
|
||||
$user->twitterAccount = $acc;
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
|
||||
$user = $this->_em->find(get_class($user), $user->id);
|
||||
$this->assertNotNull($user->twitterAccount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @ChangeTrackingPolicy("DEFERRED_EXPLICIT")
|
||||
*/
|
||||
class DDC1461User
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
* @Column(type="integer")
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @OneToOne(targetEntity="DDC1461TwitterAccount", orphanRemoval=true, fetch="EAGER", cascade = {"persist"}, inversedBy="user")
|
||||
* @var TwitterAccount
|
||||
*/
|
||||
public $twitterAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @ChangeTrackingPolicy("DEFERRED_EXPLICIT")
|
||||
*/
|
||||
class DDC1461TwitterAccount
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
* @Column(type="integer")
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @OneToOne(targetEntity="DDC1461User", fetch="EAGER")
|
||||
*/
|
||||
public $user;
|
||||
}
|
@ -25,18 +25,15 @@ class DDC331Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-331
|
||||
*/
|
||||
public function testSelectFieldOnRootEntity()
|
||||
{
|
||||
$employee = new CompanyEmployee;
|
||||
$employee->setName('Roman S. Borschel');
|
||||
$employee->setSalary(100000);
|
||||
$employee->setDepartment('IT');
|
||||
|
||||
$this->_em->persist($employee);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$q = $this->_em->createQuery('SELECT e.name FROM Doctrine\Tests\Models\Company\CompanyEmployee e');
|
||||
$this->assertEquals('SELECT c0_.name AS name0 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ ON c1_.id = c2_.id', $q->getSql());
|
||||
$this->assertEquals(
|
||||
strtolower('SELECT c0_.name AS name0 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ ON c1_.id = c2_.id'),
|
||||
strtolower($q->getSql())
|
||||
);
|
||||
}
|
||||
}
|
@ -18,7 +18,10 @@ class DDC448Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
public function testIssue()
|
||||
{
|
||||
$q = $this->_em->createQuery("select b from ".__NAMESPACE__."\\DDC448SubTable b where b.connectedClassId = ?1");
|
||||
$this->assertEquals('SELECT d0_.id AS id0, d0_.discr AS discr1, d0_.connectedClassId AS connectedClassId2 FROM SubTable s1_ INNER JOIN DDC448MainTable d0_ ON s1_.id = d0_.id WHERE d0_.connectedClassId = ?', $q->getSQL());
|
||||
$this->assertEquals(
|
||||
strtolower('SELECT d0_.id AS id0, d0_.discr AS discr1, d0_.connectedClassId AS connectedClassId2 FROM SubTable s1_ INNER JOIN DDC448MainTable d0_ ON s1_.id = d0_.id WHERE d0_.connectedClassId = ?'),
|
||||
strtolower($q->getSQL())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,10 @@ class DDC493Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
public function testIssue()
|
||||
{
|
||||
$q = $this->_em->createQuery("select u, c.data from ".__NAMESPACE__."\\DDC493Distributor u JOIN u.contact c");
|
||||
$this->assertEquals('SELECT d0_.id AS id0, d1_.data AS data1, d0_.discr AS discr2, d0_.contact AS contact3 FROM DDC493Distributor d2_ INNER JOIN DDC493Customer d0_ ON d2_.id = d0_.id INNER JOIN DDC493Contact d1_ ON d0_.contact = d1_.id', $q->getSQL());
|
||||
$this->assertEquals(
|
||||
strtolower('SELECT d0_.id AS id0, d1_.data AS data1, d0_.discr AS discr2, d0_.contact AS contact3 FROM DDC493Distributor d2_ INNER JOIN DDC493Customer d0_ ON d2_.id = d0_.id INNER JOIN DDC493Contact d1_ ON d0_.contact = d1_.id'),
|
||||
strtolower($q->getSQL())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,10 @@ class DDC513Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
public function testIssue()
|
||||
{
|
||||
$q = $this->_em->createQuery("select u from ".__NAMESPACE__."\\DDC513OfferItem u left join u.price p");
|
||||
$this->assertEquals('SELECT d0_.id AS id0, d0_.discr AS discr1, d0_.price AS price2 FROM DDC513OfferItem d1_ INNER JOIN DDC513Item d0_ ON d1_.id = d0_.id LEFT JOIN DDC513Price d2_ ON d0_.price = d2_.id', $q->getSQL());
|
||||
$this->assertEquals(
|
||||
strtolower('SELECT d0_.id AS id0, d0_.discr AS discr1, d0_.price AS price2 FROM DDC513OfferItem d1_ INNER JOIN DDC513Item d0_ ON d1_.id = d0_.id LEFT JOIN DDC513Price d2_ ON d0_.price = d2_.id'),
|
||||
strtolower($q->getSQL())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,10 @@ class DDC698Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$sql = $qb->getQuery()->getSQL();
|
||||
|
||||
$this->assertEquals('SELECT p0_.privilegeID AS privilegeID0, p0_.name AS name1, r1_.roleID AS roleID2, r1_.name AS name3, r1_.shortName AS shortName4 FROM Privileges p0_ LEFT JOIN RolePrivileges r2_ ON p0_.privilegeID = r2_.privilegeID LEFT JOIN Roles r1_ ON r1_.roleID = r2_.roleID', $sql);
|
||||
$this->assertEquals(
|
||||
strtolower('SELECT p0_.privilegeID AS privilegeID0, p0_.name AS name1, r1_.roleID AS roleID2, r1_.name AS name3, r1_.shortName AS shortName4 FROM Privileges p0_ LEFT JOIN RolePrivileges r2_ ON p0_.privilegeID = r2_.privilegeID LEFT JOIN Roles r1_ ON r1_.roleID = r2_.roleID'),
|
||||
strtolower($sql)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,10 @@ class DDC719Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
$q = $this->_em->createQuery('SELECT g, c FROM Doctrine\Tests\ORM\Functional\Ticket\DDC719Group g LEFT JOIN g.children c WHERE g.parents IS EMPTY');
|
||||
|
||||
$this->assertEquals('SELECT g0_.name AS name0, g0_.description AS description1, g0_.id AS id2, g1_.name AS name3, g1_.description AS description4, g1_.id AS id5 FROM groups g0_ LEFT JOIN groups_groups g2_ ON g0_.id = g2_.parent_id LEFT JOIN groups g1_ ON g1_.id = g2_.child_id WHERE (SELECT COUNT(*) FROM groups_groups g3_ WHERE g3_.child_id = g0_.id) = 0', $q->getSQL());
|
||||
$this->assertEquals(
|
||||
strtolower('SELECT g0_.name AS name0, g0_.description AS description1, g0_.id AS id2, g1_.name AS name3, g1_.description AS description4, g1_.id AS id5 FROM groups g0_ LEFT JOIN groups_groups g2_ ON g0_.id = g2_.parent_id LEFT JOIN groups g1_ ON g1_.id = g2_.child_id WHERE (SELECT COUNT(*) FROM groups_groups g3_ WHERE g3_.child_id = g0_.id) = 0'),
|
||||
strtolower($q->getSQL())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,12 +31,12 @@ class DDC719Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
*/
|
||||
class Entity
|
||||
{
|
||||
/**
|
||||
/**
|
||||
* @Id @GeneratedValue
|
||||
* @Column(type="integer")
|
||||
* @Column(type="integer")
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
|
||||
public function getId() { return $this->id; }
|
||||
}
|
||||
|
||||
|
@ -34,10 +34,10 @@ class DDC949Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$true = $this->_em->getRepository('Doctrine\Tests\Models\Generic\BooleanModel')->findOneBy(array('booleanField' => true));
|
||||
$false = $this->_em->getRepository('Doctrine\Tests\Models\Generic\BooleanModel')->findOneBy(array('booleanField' => false));
|
||||
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\Generic\BooleanModel', $true);
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\Generic\BooleanModel', $true, "True model not found");
|
||||
$this->assertTrue($true->booleanField, "True Boolean Model should be true.");
|
||||
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\Generic\BooleanModel', $false);
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\Generic\BooleanModel', $false, "False model not found");
|
||||
$this->assertFalse($false->booleanField, "False Boolean Model should be false.");
|
||||
}
|
||||
}
|
@ -9,13 +9,34 @@ require_once __DIR__ . '/../../TestInit.php';
|
||||
|
||||
class ArrayHydratorTest extends HydrationTestCase
|
||||
{
|
||||
public function provideDataForUserEntityResult()
|
||||
{
|
||||
return array(
|
||||
array(0),
|
||||
array('user'),
|
||||
);
|
||||
}
|
||||
|
||||
public function provideDataForMultipleRootEntityResult()
|
||||
{
|
||||
return array(
|
||||
array(0, 0),
|
||||
array('user', 0),
|
||||
array(0, 'article'),
|
||||
array('user', 'article'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select u.id, u.name from Doctrine\Tests\Models\CMS\CmsUser u
|
||||
* SELECT PARTIAL u.{id, name}
|
||||
* FROM Doctrine\Tests\Models\CMS\CmsUser u
|
||||
*
|
||||
* @dataProvider provideDataForUserEntityResult
|
||||
*/
|
||||
public function testSimpleEntityQuery()
|
||||
public function testSimpleEntityQuery($userEntityKey)
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u', $userEntityKey ?: null);
|
||||
$rsm->addFieldResult('u', 'u__id', 'id');
|
||||
$rsm->addFieldResult('u', 'u__name', 'name');
|
||||
|
||||
@ -24,35 +45,39 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__name' => 'romanb'
|
||||
),
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__name' => 'jwage'
|
||||
)
|
||||
);
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
|
||||
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
|
||||
$this->assertEquals(2, count($result));
|
||||
|
||||
$this->assertTrue(is_array($result));
|
||||
|
||||
$this->assertEquals(1, $result[0]['id']);
|
||||
$this->assertEquals('romanb', $result[0]['name']);
|
||||
|
||||
$this->assertEquals(2, $result[1]['id']);
|
||||
$this->assertEquals('jwage', $result[1]['name']);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* SELECT PARTIAL u.{id, name}, PARTIAL a.{id, topic}
|
||||
* FROM Doctrine\Tests\Models\CMS\CmsUser u, Doctrine\Tests\Models\CMS\CmsArticle a
|
||||
*
|
||||
* @dataProvider provideDataForMultipleRootEntityResult
|
||||
*/
|
||||
public function testSimpleMultipleRootEntityQuery()
|
||||
public function testSimpleMultipleRootEntityQuery($userEntityKey, $articleEntityKey)
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsArticle', 'a');
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u', $userEntityKey ?: null);
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsArticle', 'a', $articleEntityKey ?: null);
|
||||
$rsm->addFieldResult('u', 'u__id', 'id');
|
||||
$rsm->addFieldResult('u', 'u__name', 'name');
|
||||
$rsm->addFieldResult('a', 'a__id', 'id');
|
||||
@ -65,47 +90,51 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'u__name' => 'romanb',
|
||||
'a__id' => '1',
|
||||
'a__topic' => 'Cool things.'
|
||||
),
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__name' => 'jwage',
|
||||
'a__id' => '2',
|
||||
'a__topic' => 'Cool things II.'
|
||||
)
|
||||
);
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
|
||||
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
|
||||
$this->assertEquals(4, count($result));
|
||||
|
||||
$this->assertEquals(1, $result[0]['id']);
|
||||
$this->assertEquals('romanb', $result[0]['name']);
|
||||
|
||||
$this->assertEquals(1, $result[1]['id']);
|
||||
$this->assertEquals('Cool things.', $result[1]['topic']);
|
||||
|
||||
$this->assertEquals(2, $result[2]['id']);
|
||||
$this->assertEquals('jwage', $result[2]['name']);
|
||||
|
||||
$this->assertEquals(2, $result[3]['id']);
|
||||
$this->assertEquals('Cool things II.', $result[3]['topic']);
|
||||
}
|
||||
|
||||
/**
|
||||
* select u.id, u.status, p.phonenumber, upper(u.name) nameUpper from User u
|
||||
* join u.phonenumbers p
|
||||
* =
|
||||
* select u.id, u.status, p.phonenumber, upper(u.name) as u__0 from USERS u
|
||||
* INNER JOIN PHONENUMBERS p ON u.id = p.user_id
|
||||
* SELECT PARTIAL u.{id, status}, PARTIAL p.{phonenumber}, UPPER(u.name) AS nameUpper
|
||||
* FROM Doctrine\Tests\Models\CMS\CmsUser u
|
||||
* JOIN u.phonenumbers p
|
||||
*
|
||||
* @dataProvider provideDataForUserEntityResult
|
||||
*/
|
||||
public function testMixedQueryFetchJoin()
|
||||
public function testMixedQueryFetchJoin($userEntityKey)
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u', $userEntityKey ?: null);
|
||||
$rsm->addJoinedEntityResult(
|
||||
'Doctrine\Tests\Models\CMS\CmsPhonenumber', 'p',
|
||||
'u', 'phonenumbers');
|
||||
'Doctrine\Tests\Models\CMS\CmsPhonenumber',
|
||||
'p',
|
||||
'u',
|
||||
'phonenumbers'
|
||||
);
|
||||
$rsm->addFieldResult('u', 'u__id', 'id');
|
||||
$rsm->addFieldResult('u', 'u__status', 'status');
|
||||
$rsm->addScalarResult('sclr0', 'nameUpper');
|
||||
@ -119,54 +148,56 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'ROMANB',
|
||||
'p__phonenumber' => '42',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'ROMANB',
|
||||
'p__phonenumber' => '43',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'JWAGE',
|
||||
'p__phonenumber' => '91'
|
||||
)
|
||||
);
|
||||
)
|
||||
);
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
|
||||
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
|
||||
$this->assertEquals(2, count($result));
|
||||
|
||||
$this->assertTrue(is_array($result));
|
||||
$this->assertTrue(is_array($result[0]));
|
||||
$this->assertTrue(is_array($result[1]));
|
||||
|
||||
// first user => 2 phonenumbers
|
||||
$this->assertEquals(2, count($result[0][0]['phonenumbers']));
|
||||
$this->assertEquals(2, count($result[0][$userEntityKey]['phonenumbers']));
|
||||
$this->assertEquals('ROMANB', $result[0]['nameUpper']);
|
||||
|
||||
// second user => 1 phonenumber
|
||||
$this->assertEquals(1, count($result[1][0]['phonenumbers']));
|
||||
$this->assertEquals(1, count($result[1][$userEntityKey]['phonenumbers']));
|
||||
$this->assertEquals('JWAGE', $result[1]['nameUpper']);
|
||||
|
||||
$this->assertEquals(42, $result[0][0]['phonenumbers'][0]['phonenumber']);
|
||||
$this->assertEquals(43, $result[0][0]['phonenumbers'][1]['phonenumber']);
|
||||
$this->assertEquals(91, $result[1][0]['phonenumbers'][0]['phonenumber']);
|
||||
$this->assertEquals(42, $result[0][$userEntityKey]['phonenumbers'][0]['phonenumber']);
|
||||
$this->assertEquals(43, $result[0][$userEntityKey]['phonenumbers'][1]['phonenumber']);
|
||||
$this->assertEquals(91, $result[1][$userEntityKey]['phonenumbers'][0]['phonenumber']);
|
||||
}
|
||||
|
||||
/**
|
||||
* select u.id, u.status, count(p.phonenumber) numPhones from User u
|
||||
* join u.phonenumbers p group by u.status, u.id
|
||||
* =
|
||||
* select u.id, u.status, count(p.phonenumber) as p__0 from USERS u
|
||||
* INNER JOIN PHONENUMBERS p ON u.id = p.user_id group by u.id, u.status
|
||||
* SELECT PARTIAL u.{id, status}, COUNT(p.phonenumber) AS numPhones
|
||||
* FROM Doctrine\Tests\Models\CMS\CmsUser u
|
||||
* JOIN u.phonenumbers p
|
||||
* GROUP BY u.status, u.id
|
||||
*
|
||||
* @dataProvider provideDataForUserEntityResult
|
||||
*/
|
||||
public function testMixedQueryNormalJoin()
|
||||
public function testMixedQueryNormalJoin($userEntityKey)
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u', $userEntityKey ?: null);
|
||||
$rsm->addFieldResult('u', 'u__id', 'id');
|
||||
$rsm->addFieldResult('u', 'u__status', 'status');
|
||||
$rsm->addScalarResult('sclr0', 'numPhones');
|
||||
@ -178,45 +209,50 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => '2',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => '1',
|
||||
)
|
||||
);
|
||||
)
|
||||
);
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
|
||||
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
|
||||
$this->assertEquals(2, count($result));
|
||||
$this->assertTrue(is_array($result));
|
||||
$this->assertTrue(is_array($result[0]));
|
||||
$this->assertTrue(is_array($result[1]));
|
||||
|
||||
// first user => 2 phonenumbers
|
||||
$this->assertArrayHasKey($userEntityKey, $result[0]);
|
||||
$this->assertEquals(2, $result[0]['numPhones']);
|
||||
|
||||
// second user => 1 phonenumber
|
||||
$this->assertArrayHasKey($userEntityKey, $result[1]);
|
||||
$this->assertEquals(1, $result[1]['numPhones']);
|
||||
}
|
||||
|
||||
/**
|
||||
* select u.id, u.status, upper(u.name) nameUpper from User u index by u.id
|
||||
* join u.phonenumbers p indexby p.phonenumber
|
||||
* =
|
||||
* select u.id, u.status, upper(u.name) as p__0 from USERS u
|
||||
* INNER JOIN PHONENUMBERS p ON u.id = p.user_id
|
||||
* SELECT PARTIAL u.{id, status}, UPPER(u.name) nameUpper
|
||||
* FROM Doctrine\Tests\Models\CMS\CmsUser u
|
||||
* INDEX BY u.id
|
||||
* JOIN u.phonenumbers p
|
||||
* INDEX BY p.phonenumber
|
||||
*
|
||||
* @dataProvider provideDataForUserEntityResult
|
||||
*/
|
||||
public function testMixedQueryFetchJoinCustomIndex()
|
||||
public function testMixedQueryFetchJoinCustomIndex($userEntityKey)
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u', $userEntityKey ?: null);
|
||||
$rsm->addJoinedEntityResult(
|
||||
'Doctrine\Tests\Models\CMS\CmsPhonenumber',
|
||||
'p',
|
||||
'u',
|
||||
'phonenumbers'
|
||||
'Doctrine\Tests\Models\CMS\CmsPhonenumber',
|
||||
'p',
|
||||
'u',
|
||||
'phonenumbers'
|
||||
);
|
||||
$rsm->addFieldResult('u', 'u__id', 'id');
|
||||
$rsm->addFieldResult('u', 'u__status', 'status');
|
||||
@ -233,43 +269,46 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'ROMANB',
|
||||
'p__phonenumber' => '42',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'ROMANB',
|
||||
'p__phonenumber' => '43',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'JWAGE',
|
||||
'p__phonenumber' => '91'
|
||||
)
|
||||
);
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
|
||||
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
|
||||
$this->assertEquals(2, count($result));
|
||||
|
||||
$this->assertTrue(is_array($result));
|
||||
$this->assertTrue(is_array($result[0]));
|
||||
$this->assertTrue(is_array($result[1]));
|
||||
$this->assertTrue(is_array($result[2]));
|
||||
|
||||
// test the scalar values
|
||||
$this->assertEquals('ROMANB', $result[0]['nameUpper']);
|
||||
$this->assertEquals('JWAGE', $result[1]['nameUpper']);
|
||||
$this->assertEquals('ROMANB', $result[1]['nameUpper']);
|
||||
$this->assertEquals('JWAGE', $result[2]['nameUpper']);
|
||||
|
||||
// first user => 2 phonenumbers. notice the custom indexing by user id
|
||||
$this->assertEquals(2, count($result[0]['1']['phonenumbers']));
|
||||
$this->assertEquals(2, count($result[1][$userEntityKey]['phonenumbers']));
|
||||
|
||||
// second user => 1 phonenumber. notice the custom indexing by user id
|
||||
$this->assertEquals(1, count($result[1]['2']['phonenumbers']));
|
||||
$this->assertEquals(1, count($result[2][$userEntityKey]['phonenumbers']));
|
||||
|
||||
// test the custom indexing of the phonenumbers
|
||||
$this->assertTrue(isset($result[0]['1']['phonenumbers']['42']));
|
||||
$this->assertTrue(isset($result[0]['1']['phonenumbers']['43']));
|
||||
$this->assertTrue(isset($result[1]['2']['phonenumbers']['91']));
|
||||
$this->assertTrue(isset($result[1][$userEntityKey]['phonenumbers']['42']));
|
||||
$this->assertTrue(isset($result[1][$userEntityKey]['phonenumbers']['43']));
|
||||
$this->assertTrue(isset($result[2][$userEntityKey]['phonenumbers']['91']));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -288,16 +327,16 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addJoinedEntityResult(
|
||||
'Doctrine\Tests\Models\CMS\CmsPhonenumber',
|
||||
'p',
|
||||
'u',
|
||||
'phonenumbers'
|
||||
'Doctrine\Tests\Models\CMS\CmsPhonenumber',
|
||||
'p',
|
||||
'u',
|
||||
'phonenumbers'
|
||||
);
|
||||
$rsm->addJoinedEntityResult(
|
||||
'Doctrine\Tests\Models\CMS\CmsArticle',
|
||||
'a',
|
||||
'u',
|
||||
'articles'
|
||||
'Doctrine\Tests\Models\CMS\CmsArticle',
|
||||
'a',
|
||||
'u',
|
||||
'articles'
|
||||
);
|
||||
$rsm->addFieldResult('u', 'u__id', 'id');
|
||||
$rsm->addFieldResult('u', 'u__status', 'status');
|
||||
@ -316,15 +355,15 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'p__phonenumber' => '42',
|
||||
'a__id' => '1',
|
||||
'a__topic' => 'Getting things done!'
|
||||
),
|
||||
array(
|
||||
),
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'ROMANB',
|
||||
'p__phonenumber' => '43',
|
||||
'a__id' => '1',
|
||||
'a__topic' => 'Getting things done!'
|
||||
),
|
||||
),
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
@ -332,15 +371,15 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'p__phonenumber' => '42',
|
||||
'a__id' => '2',
|
||||
'a__topic' => 'ZendCon'
|
||||
),
|
||||
array(
|
||||
),
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'ROMANB',
|
||||
'p__phonenumber' => '43',
|
||||
'a__id' => '2',
|
||||
'a__topic' => 'ZendCon'
|
||||
),
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__status' => 'developer',
|
||||
@ -348,21 +387,20 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'p__phonenumber' => '91',
|
||||
'a__id' => '3',
|
||||
'a__topic' => 'LINQ'
|
||||
),
|
||||
array(
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'JWAGE',
|
||||
'p__phonenumber' => '91',
|
||||
'a__id' => '4',
|
||||
'a__topic' => 'PHP6'
|
||||
),
|
||||
);
|
||||
),
|
||||
);
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
|
||||
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
|
||||
$this->assertEquals(2, count($result));
|
||||
$this->assertTrue(is_array($result));
|
||||
@ -408,22 +446,22 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addJoinedEntityResult(
|
||||
'Doctrine\Tests\Models\CMS\CmsPhonenumber',
|
||||
'p',
|
||||
'u',
|
||||
'phonenumbers'
|
||||
'Doctrine\Tests\Models\CMS\CmsPhonenumber',
|
||||
'p',
|
||||
'u',
|
||||
'phonenumbers'
|
||||
);
|
||||
$rsm->addJoinedEntityResult(
|
||||
'Doctrine\Tests\Models\CMS\CmsArticle',
|
||||
'a',
|
||||
'u',
|
||||
'articles'
|
||||
'Doctrine\Tests\Models\CMS\CmsArticle',
|
||||
'a',
|
||||
'u',
|
||||
'articles'
|
||||
);
|
||||
$rsm->addJoinedEntityResult(
|
||||
'Doctrine\Tests\Models\CMS\CmsComment',
|
||||
'c',
|
||||
'a',
|
||||
'comments'
|
||||
'Doctrine\Tests\Models\CMS\CmsComment',
|
||||
'c',
|
||||
'a',
|
||||
'comments'
|
||||
);
|
||||
$rsm->addFieldResult('u', 'u__id', 'id');
|
||||
$rsm->addFieldResult('u', 'u__status', 'status');
|
||||
@ -446,8 +484,8 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'a__topic' => 'Getting things done!',
|
||||
'c__id' => '1',
|
||||
'c__topic' => 'First!'
|
||||
),
|
||||
array(
|
||||
),
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'ROMANB',
|
||||
@ -456,7 +494,7 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'a__topic' => 'Getting things done!',
|
||||
'c__id' => '1',
|
||||
'c__topic' => 'First!'
|
||||
),
|
||||
),
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
@ -466,8 +504,8 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'a__topic' => 'ZendCon',
|
||||
'c__id' => null,
|
||||
'c__topic' => null
|
||||
),
|
||||
array(
|
||||
),
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'ROMANB',
|
||||
@ -476,7 +514,7 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'a__topic' => 'ZendCon',
|
||||
'c__id' => null,
|
||||
'c__topic' => null
|
||||
),
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__status' => 'developer',
|
||||
@ -486,8 +524,8 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'a__topic' => 'LINQ',
|
||||
'c__id' => null,
|
||||
'c__topic' => null
|
||||
),
|
||||
array(
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'JWAGE',
|
||||
@ -496,13 +534,12 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'a__topic' => 'PHP6',
|
||||
'c__id' => null,
|
||||
'c__topic' => null
|
||||
),
|
||||
);
|
||||
),
|
||||
);
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
|
||||
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
|
||||
$this->assertEquals(2, count($result));
|
||||
$this->assertTrue(is_array($result));
|
||||
@ -565,11 +602,12 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\Forum\ForumCategory', 'c');
|
||||
$rsm->addJoinedEntityResult(
|
||||
'Doctrine\Tests\Models\Forum\ForumBoard',
|
||||
'b',
|
||||
'c',
|
||||
'boards'
|
||||
'Doctrine\Tests\Models\Forum\ForumBoard',
|
||||
'b',
|
||||
'c',
|
||||
'boards'
|
||||
);
|
||||
|
||||
$rsm->addFieldResult('c', 'c__id', 'id');
|
||||
$rsm->addFieldResult('c', 'c__position', 'position');
|
||||
$rsm->addFieldResult('c', 'c__name', 'name');
|
||||
@ -585,15 +623,15 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'b__id' => '1',
|
||||
'b__position' => '0',
|
||||
//'b__category_id' => '1'
|
||||
),
|
||||
array(
|
||||
),
|
||||
array(
|
||||
'c__id' => '2',
|
||||
'c__position' => '0',
|
||||
'c__name' => 'Second',
|
||||
'b__id' => '2',
|
||||
'b__position' => '0',
|
||||
//'b__category_id' => '2'
|
||||
),
|
||||
),
|
||||
array(
|
||||
'c__id' => '1',
|
||||
'c__position' => '0',
|
||||
@ -601,21 +639,20 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'b__id' => '3',
|
||||
'b__position' => '1',
|
||||
//'b__category_id' => '1'
|
||||
),
|
||||
array(
|
||||
),
|
||||
array(
|
||||
'c__id' => '1',
|
||||
'c__position' => '0',
|
||||
'c__name' => 'First',
|
||||
'b__id' => '4',
|
||||
'b__position' => '2',
|
||||
//'b__category_id' => '1'
|
||||
)
|
||||
);
|
||||
)
|
||||
);
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
|
||||
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
|
||||
$this->assertEquals(2, count($result));
|
||||
$this->assertTrue(is_array($result));
|
||||
@ -626,15 +663,19 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
$this->assertTrue(isset($result[1]['boards']));
|
||||
$this->assertEquals(1, count($result[1]['boards']));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* DQL: select partial u.{id,status}, a.id, a.topic, c.id as cid, c.topic as ctopic from CmsUser u left join u.articles a left join a.comments c
|
||||
*
|
||||
* SELECT PARTIAL u.{id,status}, a.id, a.topic, c.id as cid, c.topic as ctopic
|
||||
* FROM Doctrine\Tests\Models\CMS\CmsUser u
|
||||
* LEFT JOIN u.articles a
|
||||
* LEFT JOIN a.comments c
|
||||
*
|
||||
* @dataProvider provideDataForUserEntityResult
|
||||
*/
|
||||
/*public function testChainedJoinWithScalars()
|
||||
public function testChainedJoinWithScalars($entityKey)
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u', $entityKey ?: null);
|
||||
$rsm->addFieldResult('u', 'u__id', 'id');
|
||||
$rsm->addFieldResult('u', 'u__status', 'status');
|
||||
$rsm->addScalarResult('a__id', 'id');
|
||||
@ -652,7 +693,7 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'a__topic' => 'The First',
|
||||
'c__id' => '1',
|
||||
'c__topic' => 'First Comment'
|
||||
),
|
||||
),
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
@ -660,47 +701,52 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'a__topic' => 'The First',
|
||||
'c__id' => '2',
|
||||
'c__topic' => 'Second Comment'
|
||||
),
|
||||
array(
|
||||
),
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'a__id' => '42',
|
||||
'a__topic' => 'The Answer',
|
||||
'c__id' => null,
|
||||
'c__topic' => null
|
||||
),
|
||||
);
|
||||
),
|
||||
);
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
|
||||
$this->assertEquals(3, count($result));
|
||||
|
||||
$this->assertEquals(2, count($result[0][0])); // User array
|
||||
|
||||
$this->assertEquals(2, count($result[0][$entityKey])); // User array
|
||||
$this->assertEquals(1, $result[0]['id']);
|
||||
$this->assertEquals('The First', $result[0]['topic']);
|
||||
$this->assertEquals(1, $result[0]['cid']);
|
||||
$this->assertEquals('First Comment', $result[0]['ctopic']);
|
||||
|
||||
$this->assertEquals(2, count($result[1][0])); // User array, duplicated
|
||||
|
||||
$this->assertEquals(2, count($result[1][$entityKey])); // User array, duplicated
|
||||
$this->assertEquals(1, $result[1]['id']); // duplicated
|
||||
$this->assertEquals('The First', $result[1]['topic']); // duplicated
|
||||
$this->assertEquals(2, $result[1]['cid']);
|
||||
$this->assertEquals('Second Comment', $result[1]['ctopic']);
|
||||
|
||||
$this->assertEquals(2, count($result[2][0])); // User array, duplicated
|
||||
|
||||
$this->assertEquals(2, count($result[2][$entityKey])); // User array, duplicated
|
||||
$this->assertEquals(42, $result[2]['id']);
|
||||
$this->assertEquals('The Answer', $result[2]['topic']);
|
||||
$this->assertNull($result[2]['cid']);
|
||||
$this->assertNull($result[2]['ctopic']);
|
||||
}*/
|
||||
}
|
||||
|
||||
public function testResultIteration()
|
||||
/**
|
||||
* SELECT PARTIAL u.{id, status}, UPPER(u.name) AS nameUpper
|
||||
* FROM Doctrine\Tests\Models\CMS\CmsUser u
|
||||
*
|
||||
* @dataProvider provideDataForUserEntityResult
|
||||
*/
|
||||
public function testResultIteration($userEntityKey)
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u', $userEntityKey ?: null);
|
||||
$rsm->addFieldResult('u', 'u__id', 'id');
|
||||
$rsm->addFieldResult('u', 'u__name', 'name');
|
||||
|
||||
@ -709,23 +755,22 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__name' => 'romanb'
|
||||
),
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__name' => 'jwage'
|
||||
)
|
||||
);
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
|
||||
$iterator = $hydrator->iterate($stmt, $rsm);
|
||||
$rowNum = 0;
|
||||
|
||||
$iterableResult = $hydrator->iterate($stmt, $rsm);
|
||||
|
||||
$rowNum = 0;
|
||||
while (($row = $iterableResult->next()) !== false) {
|
||||
while (($row = $iterator->next()) !== false) {
|
||||
$this->assertEquals(1, count($row));
|
||||
$this->assertTrue(is_array($row[0]));
|
||||
|
||||
if ($rowNum == 0) {
|
||||
$this->assertEquals(1, $row[0]['id']);
|
||||
$this->assertEquals('romanb', $row[0]['name']);
|
||||
@ -733,17 +778,22 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
$this->assertEquals(2, $row[0]['id']);
|
||||
$this->assertEquals('jwage', $row[0]['name']);
|
||||
}
|
||||
|
||||
++$rowNum;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SELECT PARTIAL u.{id, name}
|
||||
* FROM Doctrine\Tests\Models\CMS\CmsUser u
|
||||
*
|
||||
* @group DDC-644
|
||||
* @dataProvider provideDataForUserEntityResult
|
||||
*/
|
||||
public function testSkipUnknownColumns()
|
||||
public function testSkipUnknownColumns($userEntityKey)
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u', $userEntityKey ?: null);
|
||||
$rsm->addFieldResult('u', 'u__id', 'id');
|
||||
$rsm->addFieldResult('u', 'u__name', 'name');
|
||||
|
||||
@ -753,24 +803,30 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'u__id' => '1',
|
||||
'u__name' => 'romanb',
|
||||
'foo' => 'bar', // unknown!
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
|
||||
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
|
||||
$this->assertEquals(1, count($result));
|
||||
$this->assertArrayHasKey('id', $result[0]);
|
||||
$this->assertArrayHasKey('name', $result[0]);
|
||||
$this->assertArrayNotHasKey('foo', $result[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* SELECT PARTIAL u.{id, status}, UPPER(u.name) AS nameUpper
|
||||
* FROM Doctrine\Tests\Models\CMS\CmsUser u
|
||||
*
|
||||
* @group DDC-1358
|
||||
* @dataProvider provideDataForUserEntityResult
|
||||
*/
|
||||
public function testMissingIdForRootEntity()
|
||||
public function testMissingIdForRootEntity($userEntityKey)
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u', $userEntityKey ?: null);
|
||||
$rsm->addFieldResult('u', 'u__id', 'id');
|
||||
$rsm->addFieldResult('u', 'u__status', 'status');
|
||||
$rsm->addScalarResult('sclr0', 'nameUpper');
|
||||
@ -782,28 +838,27 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'ROMANB',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'u__id' => null,
|
||||
'u__status' => null,
|
||||
'sclr0' => 'ROMANB',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'JWAGE',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'u__id' => null,
|
||||
'u__status' => null,
|
||||
'sclr0' => 'JWAGE',
|
||||
),
|
||||
);
|
||||
),
|
||||
);
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
|
||||
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
|
||||
$this->assertEquals(4, count($result), "Should hydrate four results.");
|
||||
|
||||
@ -812,9 +867,54 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
$this->assertEquals('JWAGE', $result[2]['nameUpper']);
|
||||
$this->assertEquals('JWAGE', $result[3]['nameUpper']);
|
||||
|
||||
$this->assertEquals(array('id' => 1, 'status' => 'developer'), $result[0][0]);
|
||||
$this->assertNull($result[1][0]);
|
||||
$this->assertEquals(array('id' => 2, 'status' => 'developer'), $result[2][0]);
|
||||
$this->assertNull($result[3][0]);
|
||||
$this->assertEquals(array('id' => 1, 'status' => 'developer'), $result[0][$userEntityKey]);
|
||||
$this->assertNull($result[1][$userEntityKey]);
|
||||
$this->assertEquals(array('id' => 2, 'status' => 'developer'), $result[2][$userEntityKey]);
|
||||
$this->assertNull($result[3][$userEntityKey]);
|
||||
}
|
||||
|
||||
/**
|
||||
* SELECT PARTIAL u.{id, status}, UPPER(u.name) AS nameUpper
|
||||
* FROM Doctrine\Tests\Models\CMS\CmsUser u
|
||||
* INDEX BY u.id
|
||||
*
|
||||
* @group DDC-1385
|
||||
* @dataProvider provideDataForUserEntityResult
|
||||
*/
|
||||
public function testIndexByAndMixedResult($userEntityKey)
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u', $userEntityKey ?: null);
|
||||
$rsm->addFieldResult('u', 'u__id', 'id');
|
||||
$rsm->addFieldResult('u', 'u__status', 'status');
|
||||
$rsm->addScalarResult('sclr0', 'nameUpper');
|
||||
$rsm->addIndexBy('u', 'id');
|
||||
|
||||
// Faked result set
|
||||
$resultSet = array(
|
||||
//row1
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'ROMANB',
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'JWAGE',
|
||||
),
|
||||
);
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
|
||||
$this->assertEquals(2, count($result));
|
||||
|
||||
$this->assertTrue(isset($result[1]));
|
||||
$this->assertEquals(1, $result[1][$userEntityKey]['id']);
|
||||
|
||||
$this->assertTrue(isset($result[2]));
|
||||
$this->assertEquals(2, $result[2][$userEntityKey]['id']);
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ class CustomHydratorTest extends HydrationTestCase
|
||||
|
||||
class CustomHydrator extends AbstractHydrator
|
||||
{
|
||||
protected function _hydrateAll()
|
||||
protected function hydrateAllData()
|
||||
{
|
||||
return $this->_stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -327,6 +327,51 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
|
||||
$em->getRepository("Doctrine\Tests\Models\DDC869\DDC869ChequePayment"));
|
||||
$this->assertTrue($em->getRepository("Doctrine\Tests\Models\DDC869\DDC869ChequePayment")->isTrue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1476
|
||||
*/
|
||||
public function testDefaultFieldType()
|
||||
{
|
||||
$driver = $this->_loadDriver();
|
||||
$em = $this->_getTestEntityManager();
|
||||
$factory = new \Doctrine\ORM\Mapping\ClassMetadataFactory();
|
||||
|
||||
$em->getConfiguration()->setMetadataDriverImpl($driver);
|
||||
$factory->setEntityManager($em);
|
||||
|
||||
|
||||
$class = $factory->getMetadataFor('Doctrine\Tests\Models\DDC1476\DDC1476EntityWithDefaultFieldType');
|
||||
|
||||
|
||||
$this->assertArrayHasKey('id', $class->fieldMappings);
|
||||
$this->assertArrayHasKey('name', $class->fieldMappings);
|
||||
|
||||
|
||||
$this->assertArrayHasKey('type', $class->fieldMappings['id']);
|
||||
$this->assertArrayHasKey('type', $class->fieldMappings['name']);
|
||||
|
||||
$this->assertEquals('string', $class->fieldMappings['id']['type']);
|
||||
$this->assertEquals('string', $class->fieldMappings['name']['type']);
|
||||
|
||||
|
||||
|
||||
$this->assertArrayHasKey('fieldName', $class->fieldMappings['id']);
|
||||
$this->assertArrayHasKey('fieldName', $class->fieldMappings['name']);
|
||||
|
||||
$this->assertEquals('id', $class->fieldMappings['id']['fieldName']);
|
||||
$this->assertEquals('name', $class->fieldMappings['name']['fieldName']);
|
||||
|
||||
|
||||
|
||||
$this->assertArrayHasKey('columnName', $class->fieldMappings['id']);
|
||||
$this->assertArrayHasKey('columnName', $class->fieldMappings['name']);
|
||||
|
||||
$this->assertEquals('id', $class->fieldMappings['id']['columnName']);
|
||||
$this->assertEquals('name', $class->fieldMappings['name']['columnName']);
|
||||
|
||||
$this->assertEquals(ClassMetadataInfo::GENERATOR_TYPE_NONE, $class->generatorType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -199,6 +199,20 @@ class AnnotationDriverTest extends AbstractMappingDriverTest
|
||||
|
||||
$cm = $factory->getMetadataFor('Doctrine\Tests\ORM\Mapping\ChildEntity');
|
||||
}
|
||||
|
||||
public function testInvalidFetchOptionThrowsException()
|
||||
{
|
||||
$annotationDriver = $this->_loadDriver();
|
||||
|
||||
$em = $this->_getTestEntityManager();
|
||||
$em->getConfiguration()->setMetadataDriverImpl($annotationDriver);
|
||||
$factory = new \Doctrine\ORM\Mapping\ClassMetadataFactory();
|
||||
$factory->setEntityManager($em);
|
||||
|
||||
$this->setExpectedException('Doctrine\ORM\Mapping\MappingException',
|
||||
"Entity 'Doctrine\Tests\ORM\Mapping\InvalidFetchOption' has a mapping with invalid fetch mode 'eager");
|
||||
$cm = $factory->getMetadataFor('Doctrine\Tests\ORM\Mapping\InvalidFetchOption');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -310,4 +324,15 @@ class ChildEntity extends MiddleMappedSuperclass
|
||||
* @Column(type="string")
|
||||
*/
|
||||
private $text;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class InvalidFetchOption
|
||||
{
|
||||
/**
|
||||
* @OneToMany(targetEntity="Doctrine\Tests\Models\CMS\CmsUser", fetch="eager")
|
||||
*/
|
||||
private $collection;
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->assertEquals('phonenumbers', $oneOneMapping['fieldName']);
|
||||
$this->assertEquals('Doctrine\Tests\Models\CMS\Bar', $oneOneMapping['targetEntity']);
|
||||
$this->assertTrue($cm->isReadOnly);
|
||||
$this->assertEquals(array('dql' => 'foo'), $cm->namedQueries);
|
||||
$this->assertEquals(array('dql' => array('name'=>'dql','query'=>'foo','dql'=>'foo')), $cm->namedQueries);
|
||||
}
|
||||
|
||||
public function testFieldIsNullable()
|
||||
|
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||
|
||||
$metadata->mapField(array(
|
||||
'id' => true,
|
||||
'fieldName' => 'id',
|
||||
));
|
||||
$metadata->mapField(array(
|
||||
'fieldName' => 'name'
|
||||
));
|
||||
$metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_NONE);
|
@ -0,0 +1,15 @@
|
||||
<?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\DDC1476\DDC1476EntityWithDefaultFieldType">
|
||||
<id name="id">
|
||||
<generator strategy="NONE"/>
|
||||
</id>
|
||||
|
||||
<field name="name"/>
|
||||
</entity>
|
||||
|
||||
</doctrine-mapping>
|
@ -0,0 +1,8 @@
|
||||
Doctrine\Tests\Models\DDC1476\DDC1476EntityWithDefaultFieldType:
|
||||
type: entity
|
||||
id:
|
||||
id:
|
||||
generator:
|
||||
strategy: NONE
|
||||
fields:
|
||||
name:
|
@ -17,11 +17,11 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
|
||||
/**
|
||||
* Assert a valid SQL generation.
|
||||
*
|
||||
*
|
||||
* @param string $dqlToBeTested
|
||||
* @param string $sqlToBeConfirmed
|
||||
* @param array $queryHints
|
||||
* @param array $queryParams
|
||||
* @param array $queryParams
|
||||
*/
|
||||
public function assertSqlGeneration($dqlToBeTested, $sqlToBeConfirmed, array $queryHints = array(), array $queryParams = array())
|
||||
{
|
||||
@ -34,11 +34,11 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
|
||||
$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true)
|
||||
->useQueryCache(false);
|
||||
|
||||
|
||||
foreach ($queryHints AS $name => $value) {
|
||||
$query->setHint($name, $value);
|
||||
}
|
||||
|
||||
|
||||
parent::assertEquals($sqlToBeConfirmed, $query->getSQL());
|
||||
$query->free();
|
||||
} catch (\Exception $e) {
|
||||
@ -383,7 +383,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
"SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_ WHERE c0_.discr IN ('employee')"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function testSupportsInstanceOfExpressionInWherePartWithMultipleValues()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
@ -391,7 +391,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
"SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_ WHERE c0_.discr IN ('employee', 'manager')"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1194
|
||||
*/
|
||||
@ -402,7 +402,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
"SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_ WHERE c0_.discr IN ('employee')"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1194
|
||||
*/
|
||||
@ -563,7 +563,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->_em->getClassMetadata(get_class($person))->setIdentifierValues($person, array('id' => 101));
|
||||
$q3->setParameter('param', $person);
|
||||
$this->assertEquals(
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.title AS title2, c1_.car_id AS car_id3, c2_.salary AS salary4, c2_.department AS department5, c2_.startDate AS startDate6, c0_.discr AS discr7, c0_.spouse_id AS spouse_id8 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id WHERE EXISTS (SELECT 1 FROM company_persons_friends c3_ INNER JOIN company_persons c4_ ON c3_.friend_id = c4_.id WHERE c3_.person_id = c0_.id AND c4_.id = ?)',
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.title AS title2, c2_.salary AS salary3, c2_.department AS department4, c2_.startDate AS startDate5, c0_.discr AS discr6, c0_.spouse_id AS spouse_id7, c1_.car_id AS car_id8 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id WHERE EXISTS (SELECT 1 FROM company_persons_friends c3_ INNER JOIN company_persons c4_ ON c3_.friend_id = c4_.id WHERE c3_.person_id = c0_.id AND c4_.id = ?)',
|
||||
$q3->getSql()
|
||||
);
|
||||
}
|
||||
@ -606,7 +606,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
. ')'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function testExistsExpressionWithSimpleSelectReturningScalar()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
@ -703,7 +703,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
"SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3, (SELECT COUNT(*) FROM cms_articles c1_ WHERE c1_.user_id = c0_.id) AS sclr4 FROM cms_users c0_ ORDER BY sclr4 ASC"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function testOrderBySupportsSingleValuedPathExpressionOwningSide()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
@ -711,7 +711,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
"SELECT c0_.id AS id0, c0_.topic AS topic1, c0_.text AS text2, c0_.version AS version3 FROM cms_articles c0_ ORDER BY c0_.user_id ASC"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @expectedException Doctrine\ORM\Query\QueryException
|
||||
*/
|
||||
@ -746,12 +746,12 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT b FROM Doctrine\Tests\Models\Generic\BooleanModel b WHERE b.booleanField = true",
|
||||
"SELECT b0_.id AS id0, b0_.booleanField AS booleanField1 FROM boolean_model b0_ WHERE b0_.booleanField = true"
|
||||
"SELECT b0_.id AS id0, b0_.booleanField AS booleanfield1 FROM boolean_model b0_ WHERE b0_.booleanField = true"
|
||||
);
|
||||
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT b FROM Doctrine\Tests\Models\Generic\BooleanModel b WHERE b.booleanField = false",
|
||||
"SELECT b0_.id AS id0, b0_.booleanField AS booleanField1 FROM boolean_model b0_ WHERE b0_.booleanField = false"
|
||||
"SELECT b0_.id AS id0, b0_.booleanField AS booleanfield1 FROM boolean_model b0_ WHERE b0_.booleanField = false"
|
||||
);
|
||||
|
||||
$this->_em->getConnection()->setDatabasePlatform($oldPlat);
|
||||
@ -894,7 +894,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.username = 'gblanco'",
|
||||
"SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 ".
|
||||
"SELECT c0_.id AS ID0, c0_.status AS STATUS1, c0_.username AS USERNAME2, c0_.name AS NAME3 ".
|
||||
"FROM cms_users c0_ WHERE c0_.username = 'gblanco' FOR UPDATE",
|
||||
array(Query::HINT_LOCK_MODE => \Doctrine\DBAL\LockMode::PESSIMISTIC_READ)
|
||||
);
|
||||
@ -948,7 +948,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, count(c1_.id) AS sclr2 FROM cms_groups c0_ INNER JOIN cms_users_groups c2_ ON c0_.id = c2_.group_id INNER JOIN cms_users c1_ ON c1_.id = c2_.user_id GROUP BY c0_.id'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function testCaseContainingNullIf()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
@ -956,7 +956,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
'SELECT NULLIF(c0_.id, c0_.name) AS sclr0 FROM cms_groups c0_'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function testCaseContainingCoalesce()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
@ -1026,248 +1026,281 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
"SELECT d0_.article_id AS article_id0, d0_.title AS title1, d1_.article_id AS article_id2, d1_.title AS title3 FROM DDC117Link d2_ INNER JOIN DDC117Article d0_ ON d2_.target_id = d0_.article_id INNER JOIN DDC117Article d1_ ON d2_.source_id = d1_.article_id"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function testGeneralCaseWithSingleWhenClause()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT g.id, CASE WHEN ((g.id / 2) > 18) THEN 1 ELSE 0 END AS test FROM Doctrine\Tests\Models\CMS\CmsGroup g",
|
||||
"SELECT g.id, CASE WHEN ((g.id / 2) > 18) THEN 1 ELSE 0 END AS test FROM Doctrine\Tests\Models\CMS\CmsGroup g",
|
||||
"SELECT c0_.id AS id0, CASE WHEN (c0_.id / 2 > 18) THEN 1 ELSE 0 END AS sclr1 FROM cms_groups c0_"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function testGeneralCaseWithMultipleWhenClause()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT g.id, CASE WHEN (g.id / 2 < 10) THEN 2 WHEN ((g.id / 2) > 20) THEN 1 ELSE 0 END AS test FROM Doctrine\Tests\Models\CMS\CmsGroup g",
|
||||
"SELECT g.id, CASE WHEN (g.id / 2 < 10) THEN 2 WHEN ((g.id / 2) > 20) THEN 1 ELSE 0 END AS test FROM Doctrine\Tests\Models\CMS\CmsGroup g",
|
||||
"SELECT c0_.id AS id0, CASE WHEN (c0_.id / 2 < 10) THEN 2 WHEN (c0_.id / 2 > 20) THEN 1 ELSE 0 END AS sclr1 FROM cms_groups c0_"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function testSimpleCaseWithSingleWhenClause()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT g FROM Doctrine\Tests\Models\CMS\CmsGroup g WHERE g.id = CASE g.name WHEN 'admin' THEN 1 ELSE 2 END",
|
||||
"SELECT g FROM Doctrine\Tests\Models\CMS\CmsGroup g WHERE g.id = CASE g.name WHEN 'admin' THEN 1 ELSE 2 END",
|
||||
"SELECT c0_.id AS id0, c0_.name AS name1 FROM cms_groups c0_ WHERE c0_.id = CASE c0_.name WHEN admin THEN 1 ELSE 2 END"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function testSimpleCaseWithMultipleWhenClause()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT g FROM Doctrine\Tests\Models\CMS\CmsGroup g WHERE g.id = (CASE g.name WHEN 'admin' THEN 1 WHEN 'moderator' THEN 2 ELSE 3 END)",
|
||||
"SELECT g FROM Doctrine\Tests\Models\CMS\CmsGroup g WHERE g.id = (CASE g.name WHEN 'admin' THEN 1 WHEN 'moderator' THEN 2 ELSE 3 END)",
|
||||
"SELECT c0_.id AS id0, c0_.name AS name1 FROM cms_groups c0_ WHERE c0_.id = CASE c0_.name WHEN admin THEN 1 WHEN moderator THEN 2 ELSE 3 END"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function testGeneralCaseWithSingleWhenClauseInSubselect()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT g FROM Doctrine\Tests\Models\CMS\CmsGroup g WHERE g.id IN (SELECT CASE WHEN ((g2.id / 2) > 18) THEN 2 ELSE 1 END FROM Doctrine\Tests\Models\CMS\CmsGroup g2)",
|
||||
"SELECT g FROM Doctrine\Tests\Models\CMS\CmsGroup g WHERE g.id IN (SELECT CASE WHEN ((g2.id / 2) > 18) THEN 2 ELSE 1 END FROM Doctrine\Tests\Models\CMS\CmsGroup g2)",
|
||||
"SELECT c0_.id AS id0, c0_.name AS name1 FROM cms_groups c0_ WHERE c0_.id IN (SELECT CASE WHEN (c1_.id / 2 > 18) THEN 2 ELSE 1 END AS sclr2 FROM cms_groups c1_)"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function testGeneralCaseWithMultipleWhenClauseInSubselect()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT g FROM Doctrine\Tests\Models\CMS\CmsGroup g WHERE g.id IN (SELECT CASE WHEN (g.id / 2 < 10) THEN 3 WHEN ((g.id / 2) > 20) THEN 2 ELSE 1 END FROM Doctrine\Tests\Models\CMS\CmsGroup g2)",
|
||||
"SELECT g FROM Doctrine\Tests\Models\CMS\CmsGroup g WHERE g.id IN (SELECT CASE WHEN (g.id / 2 < 10) THEN 3 WHEN ((g.id / 2) > 20) THEN 2 ELSE 1 END FROM Doctrine\Tests\Models\CMS\CmsGroup g2)",
|
||||
"SELECT c0_.id AS id0, c0_.name AS name1 FROM cms_groups c0_ WHERE c0_.id IN (SELECT CASE WHEN (c0_.id / 2 < 10) THEN 3 WHEN (c0_.id / 2 > 20) THEN 2 ELSE 1 END AS sclr2 FROM cms_groups c1_)"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function testSimpleCaseWithSingleWhenClauseInSubselect()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT g FROM Doctrine\Tests\Models\CMS\CmsGroup g WHERE g.id IN (SELECT CASE g2.name WHEN 'admin' THEN 1 ELSE 2 END FROM Doctrine\Tests\Models\CMS\CmsGroup g2)",
|
||||
"SELECT g FROM Doctrine\Tests\Models\CMS\CmsGroup g WHERE g.id IN (SELECT CASE g2.name WHEN 'admin' THEN 1 ELSE 2 END FROM Doctrine\Tests\Models\CMS\CmsGroup g2)",
|
||||
"SELECT c0_.id AS id0, c0_.name AS name1 FROM cms_groups c0_ WHERE c0_.id IN (SELECT CASE c1_.name WHEN admin THEN 1 ELSE 2 END AS sclr2 FROM cms_groups c1_)"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function testSimpleCaseWithMultipleWhenClauseInSubselect()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT g FROM Doctrine\Tests\Models\CMS\CmsGroup g WHERE g.id IN (SELECT CASE g2.name WHEN 'admin' THEN 1 WHEN 'moderator' THEN 2 ELSE 3 END FROM Doctrine\Tests\Models\CMS\CmsGroup g2)",
|
||||
"SELECT g FROM Doctrine\Tests\Models\CMS\CmsGroup g WHERE g.id IN (SELECT CASE g2.name WHEN 'admin' THEN 1 WHEN 'moderator' THEN 2 ELSE 3 END FROM Doctrine\Tests\Models\CMS\CmsGroup g2)",
|
||||
"SELECT c0_.id AS id0, c0_.name AS name1 FROM cms_groups c0_ WHERE c0_.id IN (SELECT CASE c1_.name WHEN admin THEN 1 WHEN moderator THEN 2 ELSE 3 END AS sclr2 FROM cms_groups c1_)"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1339
|
||||
*/
|
||||
public function testIdentityFunctionInSelectClause()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT IDENTITY(u.email) as email_id FROM Doctrine\Tests\Models\CMS\CmsUser u",
|
||||
"SELECT IDENTITY(u.email) as email_id FROM Doctrine\Tests\Models\CMS\CmsUser u",
|
||||
"SELECT c0_.email_id AS sclr0 FROM cms_users c0_"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1339
|
||||
*/
|
||||
public function testIdentityFunctionDoesNotAcceptStateField()
|
||||
{
|
||||
$this->assertInvalidSqlGeneration(
|
||||
"SELECT IDENTITY(u.name) as name FROM Doctrine\Tests\Models\CMS\CmsUser u",
|
||||
"SELECT IDENTITY(u.name) as name FROM Doctrine\Tests\Models\CMS\CmsUser u",
|
||||
"Doctrine\ORM\Query\QueryException"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeJoinInRootClassWithDisabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT p FROM Doctrine\Tests\Models\Company\CompanyPerson p',
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.title AS title2, c1_.car_id AS car_id3, c2_.salary AS salary4, c2_.department AS department5, c2_.startDate AS startDate6, c0_.discr AS discr7, c0_.spouse_id AS spouse_id8 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id',
|
||||
'SELECT p FROM Doctrine\Tests\Models\Company\CompanyPerson p',
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.title AS title2, c2_.salary AS salary3, c2_.department AS department4, c2_.startDate AS startDate5, c0_.discr AS discr6, c0_.spouse_id AS spouse_id7, c1_.car_id AS car_id8 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id',
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeJoinInRootClassWithEnabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT p FROM Doctrine\Tests\Models\Company\CompanyPerson p',
|
||||
'SELECT p FROM Doctrine\Tests\Models\Company\CompanyPerson p',
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_',
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => true)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeJoinInChildClassWithDisabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e',
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c2_.title AS title5, c2_.car_id AS car_id6, c0_.discr AS discr7, c0_.spouse_id AS spouse_id8 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ ON c1_.id = c2_.id',
|
||||
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e',
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c2_.title AS title5, c0_.discr AS discr6, c0_.spouse_id AS spouse_id7, c2_.car_id AS car_id8 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ ON c1_.id = c2_.id',
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeJoinInChildClassWithEnabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e',
|
||||
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e',
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c0_.discr AS discr5 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id',
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => true)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeJoinInLeafClassWithDisabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT m FROM Doctrine\Tests\Models\Company\CompanyManager m',
|
||||
'SELECT m FROM Doctrine\Tests\Models\Company\CompanyManager m',
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c2_.title AS title5, c0_.discr AS discr6, c0_.spouse_id AS spouse_id7, c2_.car_id AS car_id8 FROM company_managers c2_ INNER JOIN company_employees c1_ ON c2_.id = c1_.id INNER JOIN company_persons c0_ ON c2_.id = c0_.id',
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeJoinInLeafClassWithEnabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT m FROM Doctrine\Tests\Models\Company\CompanyManager m',
|
||||
'SELECT m FROM Doctrine\Tests\Models\Company\CompanyManager m',
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c2_.title AS title5, c0_.discr AS discr6 FROM company_managers c2_ INNER JOIN company_employees c1_ ON c2_.id = c1_.id INNER JOIN company_persons c0_ ON c2_.id = c0_.id',
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => true)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeSingleTableInRootClassWithDisabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c',
|
||||
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c',
|
||||
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.fixPrice AS fixPrice2, c0_.hoursWorked AS hoursWorked3, c0_.pricePerHour AS pricePerHour4, c0_.maxPrice AS maxPrice5, c0_.discr AS discr6, c0_.salesPerson_id AS salesPerson_id7 FROM company_contracts c0_ WHERE c0_.discr IN ('fix', 'flexible', 'flexultra')",
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeSingleTableInRootClassWithEnabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c',
|
||||
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c',
|
||||
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.fixPrice AS fixPrice2, c0_.hoursWorked AS hoursWorked3, c0_.pricePerHour AS pricePerHour4, c0_.maxPrice AS maxPrice5, c0_.discr AS discr6 FROM company_contracts c0_ WHERE c0_.discr IN ('fix', 'flexible', 'flexultra')",
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => true)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeSingleTableInChildClassWithDisabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT fc FROM Doctrine\Tests\Models\Company\CompanyFlexContract fc',
|
||||
'SELECT fc FROM Doctrine\Tests\Models\Company\CompanyFlexContract fc',
|
||||
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.hoursWorked AS hoursWorked2, c0_.pricePerHour AS pricePerHour3, c0_.maxPrice AS maxPrice4, c0_.discr AS discr5, c0_.salesPerson_id AS salesPerson_id6 FROM company_contracts c0_ WHERE c0_.discr IN ('flexible', 'flexultra')",
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeSingleTableInChildClassWithEnabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT fc FROM Doctrine\Tests\Models\Company\CompanyFlexContract fc',
|
||||
'SELECT fc FROM Doctrine\Tests\Models\Company\CompanyFlexContract fc',
|
||||
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.hoursWorked AS hoursWorked2, c0_.pricePerHour AS pricePerHour3, c0_.maxPrice AS maxPrice4, c0_.discr AS discr5 FROM company_contracts c0_ WHERE c0_.discr IN ('flexible', 'flexultra')",
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => true)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeSingleTableInLeafClassWithDisabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT fuc FROM Doctrine\Tests\Models\Company\CompanyFlexUltraContract fuc',
|
||||
'SELECT fuc FROM Doctrine\Tests\Models\Company\CompanyFlexUltraContract fuc',
|
||||
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.hoursWorked AS hoursWorked2, c0_.pricePerHour AS pricePerHour3, c0_.maxPrice AS maxPrice4, c0_.discr AS discr5, c0_.salesPerson_id AS salesPerson_id6 FROM company_contracts c0_ WHERE c0_.discr IN ('flexultra')",
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeSingleTableInLeafClassWithEnabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT fuc FROM Doctrine\Tests\Models\Company\CompanyFlexUltraContract fuc',
|
||||
'SELECT fuc FROM Doctrine\Tests\Models\Company\CompanyFlexUltraContract fuc',
|
||||
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.hoursWorked AS hoursWorked2, c0_.pricePerHour AS pricePerHour3, c0_.maxPrice AS maxPrice4, c0_.discr AS discr5 FROM company_contracts c0_ WHERE c0_.discr IN ('flexultra')",
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => true)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1161
|
||||
*/
|
||||
public function testSelfReferenceWithOneToOneDoesNotDuplicateAlias()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT p, pp FROM Doctrine\Tests\Models\Company\CompanyPerson p JOIN p.spouse pp',
|
||||
"SELECT c0_.id AS id0, c0_.name AS name1, c1_.title AS title2, c1_.car_id AS car_id3, c2_.salary AS salary4, c2_.department AS department5, c2_.startDate AS startDate6, c3_.id AS id7, c3_.name AS name8, c4_.title AS title9, c4_.car_id AS car_id10, c5_.salary AS salary11, c5_.department AS department12, c5_.startDate AS startDate13, c0_.discr AS discr14, c0_.spouse_id AS spouse_id15, c3_.discr AS discr16, c3_.spouse_id AS spouse_id17 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id INNER JOIN company_persons c3_ ON c0_.spouse_id = c3_.id LEFT JOIN company_managers c4_ ON c3_.id = c4_.id LEFT JOIN company_employees c5_ ON c3_.id = c5_.id",
|
||||
'SELECT p, pp FROM Doctrine\Tests\Models\Company\CompanyPerson p JOIN p.spouse pp',
|
||||
"SELECT c0_.id AS id0, c0_.name AS name1, c1_.title AS title2, c2_.salary AS salary3, c2_.department AS department4, c2_.startDate AS startDate5, c3_.id AS id6, c3_.name AS name7, c4_.title AS title8, c5_.salary AS salary9, c5_.department AS department10, c5_.startDate AS startDate11, c0_.discr AS discr12, c0_.spouse_id AS spouse_id13, c1_.car_id AS car_id14, c3_.discr AS discr15, c3_.spouse_id AS spouse_id16, c4_.car_id AS car_id17 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id INNER JOIN company_persons c3_ ON c0_.spouse_id = c3_.id LEFT JOIN company_managers c4_ ON c3_.id = c4_.id LEFT JOIN company_employees c5_ ON c3_.id = c5_.id",
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1384
|
||||
*/
|
||||
public function testAliasDoesNotExceedPlatformDefinedLength()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT m FROM ' . __NAMESPACE__ . '\\DDC1384Model m',
|
||||
"SELECT d0_.aVeryLongIdentifierThatShouldBeShortenedByTheSQLWalker_fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo AS fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0 FROM DDC1384Model d0_"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-331
|
||||
* @group DDC-1384
|
||||
*/
|
||||
public function testIssue331()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT e.name FROM Doctrine\Tests\Models\Company\CompanyEmployee e',
|
||||
'SELECT c0_.name AS name0 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id'
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @group DDC-1435
|
||||
*/
|
||||
public function testForeignKeyAsPrimaryKeySubselect()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT s FROM Doctrine\Tests\Models\DDC117\DDC117Article s WHERE EXISTS (SELECT r FROM Doctrine\Tests\Models\DDC117\DDC117Reference r WHERE r.source = s)",
|
||||
"SELECT d0_.article_id AS article_id0, d0_.title AS title1 FROM DDC117Article d0_ WHERE EXISTS (SELECT d1_.source_id, d1_.target_id FROM DDC117Reference d1_ WHERE d1_.source_id = d0_.article_id)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1294,7 +1327,19 @@ class MyAbsFunction extends \Doctrine\ORM\Query\AST\Functions\FunctionNode
|
||||
$parser->match(\Doctrine\ORM\Query\Lexer::T_OPEN_PARENTHESIS);
|
||||
|
||||
$this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression();
|
||||
|
||||
|
||||
$parser->match(\Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1384Model
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @Column(type="integer")
|
||||
* @GeneratedValue
|
||||
*/
|
||||
protected $aVeryLongIdentifierThatShouldBeShortenedByTheSQLWalker_fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo;
|
||||
}
|
||||
|
@ -71,4 +71,88 @@ class SchemaValidatorTest extends \Doctrine\Tests\OrmTestCase
|
||||
));
|
||||
$this->validator->validateMapping();
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1439
|
||||
*/
|
||||
public function testInvalidManyToManyJoinColumnSchema()
|
||||
{
|
||||
$class1 = $this->em->getClassMetadata(__NAMESPACE__ . '\InvalidEntity1');
|
||||
$class2 = $this->em->getClassMetadata(__NAMESPACE__ . '\InvalidEntity2');
|
||||
|
||||
$ce = $this->validator->validateClass($class1);
|
||||
|
||||
$this->assertEquals(
|
||||
array(
|
||||
"The inverse join columns of the many-to-many table 'Entity1Entity2' have to contain to ALL identifier columns of the target entity 'Doctrine\Tests\ORM\Tools\InvalidEntity2', however 'key4' are missing.",
|
||||
"The join columns of the many-to-many table 'Entity1Entity2' have to contain to ALL identifier columns of the source entity 'Doctrine\Tests\ORM\Tools\InvalidEntity1', however 'key2' are missing."
|
||||
),
|
||||
$ce
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1439
|
||||
*/
|
||||
public function testInvalidToOneJoinColumnSchema()
|
||||
{
|
||||
$class1 = $this->em->getClassMetadata(__NAMESPACE__ . '\InvalidEntity1');
|
||||
$class2 = $this->em->getClassMetadata(__NAMESPACE__ . '\InvalidEntity2');
|
||||
|
||||
$ce = $this->validator->validateClass($class2);
|
||||
|
||||
$this->assertEquals(
|
||||
array(
|
||||
"The referenced column name 'id' does not have a corresponding field with this column name on the class 'Doctrine\Tests\ORM\Tools\InvalidEntity1'.",
|
||||
"The join columns of the association 'assoc' have to match to ALL identifier columns of the source entity 'Doctrine\Tests\ORM\Tools\InvalidEntity2', however 'key3, key4' are missing."
|
||||
),
|
||||
$ce
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class InvalidEntity1
|
||||
{
|
||||
/**
|
||||
* @Id @Column
|
||||
*/
|
||||
protected $key1;
|
||||
/**
|
||||
* @Id @Column
|
||||
*/
|
||||
protected $key2;
|
||||
/**
|
||||
* @ManyToMany (targetEntity="InvalidEntity2")
|
||||
* @JoinTable (name="Entity1Entity2",
|
||||
* joinColumns={@JoinColumn(name="key1", referencedColumnName="key1")},
|
||||
* inverseJoinColumns={@JoinColumn(name="key3", referencedColumnName="key3")}
|
||||
* )
|
||||
*/
|
||||
protected $entity2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class InvalidEntity2
|
||||
{
|
||||
/**
|
||||
* @Id @Column
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
protected $key3;
|
||||
|
||||
/**
|
||||
* @Id @Column
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
protected $key4;
|
||||
|
||||
/**
|
||||
* @ManyToOne(targetEntity="InvalidEntity1")
|
||||
*/
|
||||
protected $assoc;
|
||||
}
|
32
tests/travis/mysql.travis.xml
Normal file
32
tests/travis/mysql.travis.xml
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<phpunit>
|
||||
<php>
|
||||
<var name="db_type" value="pdo_mysql"/>
|
||||
<var name="db_host" value="localhost" />
|
||||
<var name="db_username" value="travis" />
|
||||
<var name="db_password" value="" />
|
||||
<var name="db_name" value="doctrine_tests" />
|
||||
<var name="db_port" value="3306"/>
|
||||
|
||||
<var name="tmpdb_type" value="pdo_mysql"/>
|
||||
<var name="tmpdb_host" value="localhost" />
|
||||
<var name="tmpdb_username" value="travis" />
|
||||
<var name="tmpdb_password" value="" />
|
||||
<var name="tmpdb_name" value="doctrine_tests_tmp" />
|
||||
<var name="tmpdb_port" value="3306"/>
|
||||
</php>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="Doctrine ORM Test Suite">
|
||||
<directory>./../Doctrine/Tests/ORM</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<groups>
|
||||
<exclude>
|
||||
<group>performance</group>
|
||||
<group>locking_functional</group>
|
||||
</exclude>
|
||||
</groups>
|
||||
|
||||
</phpunit>
|
||||
|
34
tests/travis/pgsql.travis.xml
Normal file
34
tests/travis/pgsql.travis.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<phpunit>
|
||||
<php>
|
||||
<!-- "Real" test database -->
|
||||
<var name="db_type" value="pdo_pgsql"/>
|
||||
<var name="db_host" value="localhost" />
|
||||
<var name="db_username" value="postgres" />
|
||||
<var name="db_password" value="" />
|
||||
<var name="db_name" value="doctrine_tests" />
|
||||
<var name="db_port" value="5432"/>
|
||||
<!--<var name="db_event_subscribers" value="Doctrine\DBAL\Event\Listeners\OracleSessionInit">-->
|
||||
|
||||
<!-- Database for temporary connections (i.e. to drop/create the main database) -->
|
||||
<var name="tmpdb_type" value="pdo_pgsql"/>
|
||||
<var name="tmpdb_host" value="localhost" />
|
||||
<var name="tmpdb_username" value="postgres" />
|
||||
<var name="tmpdb_password" value="" />
|
||||
<var name="tmpdb_name" value="doctrine_tests_tmp" />
|
||||
<var name="tmpdb_port" value="5432"/>
|
||||
</php>
|
||||
<testsuites>
|
||||
<testsuite name="Doctrine ORM Test Suite">
|
||||
<directory>./../Doctrine/Tests/ORM</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<groups>
|
||||
<exclude>
|
||||
<group>performance</group>
|
||||
<group>locking_functional</group>
|
||||
</exclude>
|
||||
</groups>
|
||||
|
||||
</phpunit>
|
15
tests/travis/sqlite.travis.xml
Normal file
15
tests/travis/sqlite.travis.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<phpunit>
|
||||
<testsuites>
|
||||
<testsuite name="Doctrine ORM Test Suite">
|
||||
<directory>./../Doctrine/Tests/ORM</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<groups>
|
||||
<exclude>
|
||||
<group>performance</group>
|
||||
<group>locking_functional</group>
|
||||
</exclude>
|
||||
</groups>
|
||||
|
||||
</phpunit>
|
Loading…
x
Reference in New Issue
Block a user