diff --git a/UPGRADE_TO_2_2 b/UPGRADE_TO_2_2
index 220fb39f9..757413029 100644
--- a/UPGRADE_TO_2_2
+++ b/UPGRADE_TO_2_2
@@ -1,3 +1,17 @@
+# ResultCache implementation rewritten
+
+The result cache is completly rewritten and now works on the database result level, not inside the ORM AbstractQuery
+anymore. This means that for result cached queries the hydration will now always be performed again, regardless of
+the hydration mode. Affected areas are:
+
+1. Fixes the problem that entities coming from the result cache were not registered in the UnitOfWork
+ leading to problems during EntityManager#flush. Calls to EntityManager#merge are not necessary anymore.
+2. Affects the array hydrator which now includes the overhead of hydration compared to caching the final result.
+
+The API is backwards compatible however most of the getter methods on the `AbstractQuery` object are now
+deprecated in favor of calling AbstractQuery#getQueryCacheProfile(). This method returns a `Doctrine\DBAL\Cache\QueryCacheProfile`
+instance with access to result cache driver, lifetime and cache key.
+
# EntityManager#getPartialReference() creates read-only entity
Entities returned from EntityManager#getPartialReference() are now marked as read-only if they
diff --git a/lib/Doctrine/ORM/AbstractQuery.php b/lib/Doctrine/ORM/AbstractQuery.php
index 5d71cf0aa..72eab194b 100644
--- a/lib/Doctrine/ORM/AbstractQuery.php
+++ b/lib/Doctrine/ORM/AbstractQuery.php
@@ -20,7 +20,8 @@
namespace Doctrine\ORM;
use Doctrine\DBAL\Types\Type,
- Doctrine\ORM\Query\QueryException;
+ Doctrine\ORM\Query\QueryException,
+ Doctrine\DBAL\Cache\QueryCacheProfile;
/**
* Base contract for ORM queries. Base class for Query and NativeQuery.
@@ -91,34 +92,15 @@ abstract class AbstractQuery
protected $_hydrationMode = self::HYDRATE_OBJECT;
/**
- * The locally set cache driver used for caching result sets of this query.
- *
- * @var CacheDriver
+ * @param \Doctrine\DBAL\Cache\QueryCacheProfile
*/
- protected $_resultCacheDriver;
-
- /**
- * Boolean flag for whether or not to cache the results of this query.
- *
- * @var boolean
- */
- protected $_useResultCache;
-
- /**
- * @var string The id to store the result cache entry under.
- */
- protected $_resultCacheId;
+ protected $_queryCacheProfile;
/**
* @var boolean Boolean value that indicates whether or not expire the result cache.
*/
protected $_expireResultCache = false;
- /**
- * @var int Result Cache lifetime.
- */
- protected $_resultCacheTTL;
-
/**
* Initializes a new instance of a class derived from AbstractQuery.
*
@@ -260,7 +242,7 @@ abstract class AbstractQuery
}
/**
- * Defines a cache driver to be used for caching result sets.
+ * Defines a cache driver to be used for caching result sets and implictly enables caching.
*
* @param Doctrine\Common\Cache\Cache $driver Cache driver
* @return Doctrine\ORM\AbstractQuery
@@ -270,9 +252,10 @@ abstract class AbstractQuery
if ($resultCacheDriver !== null && ! ($resultCacheDriver instanceof \Doctrine\Common\Cache\Cache)) {
throw ORMException::invalidResultCacheDriver();
}
- $this->_resultCacheDriver = $resultCacheDriver;
- if ($resultCacheDriver) {
- $this->_useResultCache = true;
+ if ($this->_queryCacheProfile) {
+ $this->_queryCacheProfile = $this->_queryCacheProfile->setResultCacheDriver($resultCacheDriver);
+ } else {
+ $this->_queryCacheProfile = new QueryCacheProfile(0, null, $resultCacheDriver);
}
return $this;
}
@@ -280,12 +263,13 @@ abstract class AbstractQuery
/**
* Returns the cache driver used for caching result sets.
*
+ * @deprecated
* @return Doctrine\Common\Cache\Cache Cache driver
*/
public function getResultCacheDriver()
{
- if ($this->_resultCacheDriver) {
- return $this->_resultCacheDriver;
+ if ($this->_queryCacheProfile && $this->_queryCacheProfile->getResultCacheDriver()) {
+ return $this->_queryCacheProfile->getResultCacheDriver();
} else {
return $this->_em->getConfiguration()->getResultCacheImpl();
}
@@ -296,18 +280,17 @@ abstract class AbstractQuery
* how long and which ID to use for the cache entry.
*
* @param boolean $bool
- * @param integer $timeToLive
+ * @param integer $lifetime
* @param string $resultCacheId
* @return Doctrine\ORM\AbstractQuery This query instance.
*/
- public function useResultCache($bool, $timeToLive = null, $resultCacheId = null)
+ public function useResultCache($bool, $lifetime = null, $resultCacheId = null)
{
- $this->_useResultCache = $bool;
- if ($timeToLive) {
- $this->setResultCacheLifetime($timeToLive);
- }
- if ($resultCacheId) {
- $this->_resultCacheId = $resultCacheId;
+ if ($bool) {
+ $this->setResultCacheLifetime($lifetime);
+ $this->setResultCacheId($resultCacheId);
+ } else {
+ $this->_queryCacheProfile = null;
}
return $this;
}
@@ -315,27 +298,33 @@ abstract class AbstractQuery
/**
* Defines how long the result cache will be active before expire.
*
- * @param integer $timeToLive How long the cache entry is valid.
+ * @param integer $lifetime How long the cache entry is valid.
* @return Doctrine\ORM\AbstractQuery This query instance.
*/
- public function setResultCacheLifetime($timeToLive)
+ public function setResultCacheLifetime($lifetime)
{
- if ($timeToLive !== null) {
- $timeToLive = (int) $timeToLive;
+ if ($lifetime === null) {
+ $lifetime = 0;
+ } else {
+ $lifetime = (int)$lifetime;
+ }
+ if ($this->_queryCacheProfile) {
+ $this->_queryCacheProfile = $this->_queryCacheProfile->setLifetime($lifetime);
+ } else {
+ $this->_queryCacheProfile = new QueryCacheProfile($lifetime);
}
-
- $this->_resultCacheTTL = $timeToLive;
return $this;
}
/**
* Retrieves the lifetime of resultset cache.
*
+ * @deprecated
* @return integer
*/
public function getResultCacheLifetime()
{
- return $this->_resultCacheTTL;
+ return $this->_queryCacheProfile ? $this->_queryCacheProfile->getLifetime() : 0;
}
/**
@@ -360,6 +349,14 @@ abstract class AbstractQuery
return $this->_expireResultCache;
}
+ /**
+ * @return QueryCacheProfile
+ */
+ public function getQueryCacheProfile()
+ {
+ return $this->_queryCacheProfile;
+ }
+
/**
* Change the default fetch mode of an association for this query.
*
@@ -548,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)
{
@@ -584,28 +581,6 @@ abstract class AbstractQuery
$this->setParameters($params);
}
- // Check result cache
- if ($this->_useResultCache && $cacheDriver = $this->getResultCacheDriver()) {
- list($key, $hash) = $this->getResultCacheId();
- $cached = $this->_expireResultCache ? false : $cacheDriver->fetch($hash);
-
- if ($cached === false || !isset($cached[$key])) {
- // Cache miss.
- $stmt = $this->_doExecute();
-
- $result = $this->_em->getHydrator($this->_hydrationMode)->hydrateAll(
- $stmt, $this->_resultSetMapping, $this->_hints
- );
-
- $cacheDriver->save($hash, array($key => $result), $this->_resultCacheTTL);
-
- return $result;
- } else {
- // Cache hit.
- return $cached[$key];
- }
- }
-
$stmt = $this->_doExecute();
if (is_numeric($stmt)) {
@@ -627,43 +602,23 @@ abstract class AbstractQuery
*/
public function setResultCacheId($id)
{
- $this->_resultCacheId = $id;
+ if ($this->_queryCacheProfile) {
+ $this->_queryCacheProfile = $this->_queryCacheProfile->setCacheKey($id);
+ } else {
+ $this->_queryCacheProfile = new QueryCacheProfile(0, $id);
+ }
return $this;
}
/**
- * Get the result cache id to use to store the result set cache entry.
- * Will return the configured id if it exists otherwise a hash will be
- * automatically generated for you.
+ * Get the result cache id to use to store the result set cache entry if set.
*
- * @return array ($key, $hash)
+ * @deprecated
+ * @return string
*/
- protected function getResultCacheId()
+ public function getResultCacheId()
{
- if ($this->_resultCacheId) {
- return array($this->_resultCacheId, $this->_resultCacheId);
- } else {
- $params = $this->_params;
- foreach ($params AS $key => $value) {
- if (is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(get_class($value))) {
- if ($this->_em->getUnitOfWork()->getEntityState($value) == UnitOfWork::STATE_MANAGED) {
- $idValues = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
- } else {
- $class = $this->_em->getClassMetadata(get_class($value));
- $idValues = $class->getIdentifierValues($value);
- }
- $params[$key] = $idValues;
- } else {
- $params[$key] = $value;
- }
- }
-
- $sql = $this->getSql();
- ksort($this->_hints);
- $key = implode(";", (array)$sql) . var_export($params, true) .
- var_export($this->_hints, true)."&hydrationMode=".$this->_hydrationMode;
- return array($key, md5($key));
- }
+ return $this->_queryCacheProfile ? $this->_queryCacheProfile->getCacheKey() : null;
}
/**
diff --git a/lib/Doctrine/ORM/Configuration.php b/lib/Doctrine/ORM/Configuration.php
index ee6496087..eaa4df562 100644
--- a/lib/Doctrine/ORM/Configuration.php
+++ b/lib/Doctrine/ORM/Configuration.php
@@ -209,27 +209,6 @@ class Configuration extends \Doctrine\DBAL\Configuration
$this->_attributes['metadataDriverImpl'] : null;
}
- /**
- * Gets the cache driver implementation that is used for query result caching.
- *
- * @return \Doctrine\Common\Cache\Cache
- */
- public function getResultCacheImpl()
- {
- return isset($this->_attributes['resultCacheImpl']) ?
- $this->_attributes['resultCacheImpl'] : null;
- }
-
- /**
- * Sets the cache driver implementation that is used for query result caching.
- *
- * @param \Doctrine\Common\Cache\Cache $cacheImpl
- */
- public function setResultCacheImpl(Cache $cacheImpl)
- {
- $this->_attributes['resultCacheImpl'] = $cacheImpl;
- }
-
/**
* Gets the cache driver implementation that is used for the query cache (SQL cache).
*
diff --git a/lib/Doctrine/ORM/Event/EntityEventDelegator.php b/lib/Doctrine/ORM/Event/EntityEventDelegator.php
index d7c46e68e..09532bc4b 100644
--- a/lib/Doctrine/ORM/Event/EntityEventDelegator.php
+++ b/lib/Doctrine/ORM/Event/EntityEventDelegator.php
@@ -19,14 +19,16 @@
namespace Doctrine\ORM\Event;
-use \Doctrine\Common\EventSubscriber;
-use \LogicException;
+use Doctrine\Common\EventSubscriber;
+use LogicException;
/**
* Delegate events only for certain entities they are registered for.
*
- * @author Benjamin Eberlei
- * @since 2.2
+ * @link www.doctrine-project.org
+ * @author Benjamin Eberlei
+ * @author Guilherme Blanco
+ * @since 2.2
*/
class EntityEventDelegator implements EventSubscriber
{
@@ -54,17 +56,23 @@ class EntityEventDelegator implements EventSubscriber
public function addEventListener($events, $entities, $listener)
{
if ($this->frozen) {
- throw new LogicException("Cannot add event listeners after EntityEventDelegator::getSubscribedEvents() " .
- "is called once. This happens when you register the delegator with the event manager.");
+ throw new LogicException(
+ "Cannot add event listeners after EntityEventDelegator::getSubscribedEvents() " .
+ "is called once. This happens when you register the delegator with the event manager."
+ );
}
// Picks the hash code related to that listener
- $hash = spl_object_hash($listener);
+ $hash = spl_object_hash($listener);
+ $entities = array_flip((array) $entities);
foreach ((array) $events as $event) {
// Overrides listener if a previous one was associated already
// Prevents duplicate listeners on same event (same instance only)
- $this->listeners[$event][$hash] = array('listener' => $listener, 'entities' => array_flip((array)$entities));
+ $this->listeners[$event][$hash] = array(
+ 'listener' => $listener,
+ 'entities' => $entities
+ );
}
}
@@ -73,6 +81,7 @@ class EntityEventDelegator implements EventSubscriber
* interested in and added as a listener for these events.
*
* @param Doctrine\Common\EventSubscriber $subscriber The subscriber.
+ * @param array $entities
*/
public function addEventSubscriber(EventSubscriber $subscriber, $entities)
{
@@ -87,24 +96,27 @@ class EntityEventDelegator implements EventSubscriber
public function getSubscribedEvents()
{
$this->frozen = true;
+
return array_keys($this->listeners);
}
/**
* Delegate the event to an appropriate listener
*
- * @param $eventName
- * @param $event
+ * @param string $eventName
+ * @param array $args
* @return void
*/
public function __call($eventName, $args)
{
$event = $args[0];
+
foreach ($this->listeners[$eventName] AS $listenerData) {
$class = get_class($event->getEntity());
- if (isset($listenerData['entities'][$class])) {
- $listenerData['listener']->$eventName($event);
- }
+
+ if ( ! isset($listenerData['entities'][$class])) continue;
+
+ $listenerData['listener']->$eventName($event);
}
}
}
diff --git a/lib/Doctrine/ORM/Event/LifecycleEventArgs.php b/lib/Doctrine/ORM/Event/LifecycleEventArgs.php
index a5dd39cfd..0c91d8475 100644
--- a/lib/Doctrine/ORM/Event/LifecycleEventArgs.php
+++ b/lib/Doctrine/ORM/Event/LifecycleEventArgs.php
@@ -19,42 +19,59 @@
namespace Doctrine\ORM\Event;
+use Doctrine\Common\EventArgs;
+use Doctrine\ORM\EntityManager;
+
/**
* Lifecycle Events are triggered by the UnitOfWork during lifecycle transitions
* of entities.
*
- * @since 2.0
+ * @link www.doctrine-project.org
+ * @since 2.0
* @author Roman Borschel
* @author Benjamin Eberlei
*/
-class LifecycleEventArgs extends \Doctrine\Common\EventArgs
+class LifecycleEventArgs extends EventArgs
{
/**
- * @var EntityManager
+ * @var Doctrine\ORM\EntityManager
*/
- private $_em;
+ private $em;
/**
* @var object
*/
- private $_entity;
+ private $entity;
- public function __construct($entity, $em)
+ /**
+ * Constructor
+ *
+ * @param object $entity
+ * @param Doctrine\ORM\EntityManager $em
+ */
+ public function __construct($entity, EntityManager $em)
{
- $this->_entity = $entity;
- $this->_em = $em;
+ $this->entity = $entity;
+ $this->em = $em;
}
+ /**
+ * Retireve associated Entity.
+ *
+ * @return object
+ */
public function getEntity()
{
- return $this->_entity;
+ return $this->entity;
}
/**
- * @return EntityManager
+ * Retrieve associated EntityManager.
+ *
+ * @return Doctrine\ORM\EntityManager
*/
public function getEntityManager()
{
- return $this->_em;
+ return $this->em;
}
}
\ No newline at end of file
diff --git a/lib/Doctrine/ORM/Event/LoadClassMetadataEventArgs.php b/lib/Doctrine/ORM/Event/LoadClassMetadataEventArgs.php
index f00520a20..a87f45cc3 100644
--- a/lib/Doctrine/ORM/Event/LoadClassMetadataEventArgs.php
+++ b/lib/Doctrine/ORM/Event/LoadClassMetadataEventArgs.php
@@ -1,9 +1,25 @@
.
+ */
namespace Doctrine\ORM\Event;
use Doctrine\Common\EventArgs;
-
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\EntityManager;
@@ -11,32 +27,36 @@ use Doctrine\ORM\EntityManager;
* Class that holds event arguments for a loadMetadata event.
*
* @author Jonathan H. Wage
- * @since 2.0
+ * @since 2.0
*/
class LoadClassMetadataEventArgs extends EventArgs
{
/**
- * @var ClassMetadata
+ * @var Doctrine\ORM\Mapping\ClassMetadata
*/
private $classMetadata;
/**
- * @var EntityManager
+ * @var Doctrine\ORM\EntityManager
*/
private $em;
/**
- * @param ClassMetadataInfo $classMetadata
- * @param EntityManager $em
+ * Constructor.
+ *
+ * @param Doctrine\ORM\Mapping\ClassMetadataInfo $classMetadata
+ * @param Doctrine\ORM\EntityManager $em
*/
public function __construct(ClassMetadataInfo $classMetadata, EntityManager $em)
{
$this->classMetadata = $classMetadata;
- $this->em = $em;
+ $this->em = $em;
}
/**
- * @return ClassMetadataInfo
+ * Retrieve associated ClassMetadata.
+ *
+ * @return Doctrine\ORM\Mapping\ClassMetadataInfo
*/
public function getClassMetadata()
{
@@ -44,7 +64,9 @@ class LoadClassMetadataEventArgs extends EventArgs
}
/**
- * @return EntityManager
+ * Retrieve associated EntityManager.
+ *
+ * @return Doctrine\ORM\EntityManager
*/
public function getEntityManager()
{
diff --git a/lib/Doctrine/ORM/Event/OnClearEventArgs.php b/lib/Doctrine/ORM/Event/OnClearEventArgs.php
index 60ce4b3eb..49b5e8695 100644
--- a/lib/Doctrine/ORM/Event/OnClearEventArgs.php
+++ b/lib/Doctrine/ORM/Event/OnClearEventArgs.php
@@ -15,7 +15,7 @@
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* .
-*/
+ */
namespace Doctrine\ORM\Event;
@@ -23,16 +23,15 @@ namespace Doctrine\ORM\Event;
* Provides event arguments for the onClear event.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
- * @link www.doctrine-project.com
+ * @link www.doctrine-project.org
* @since 2.0
- * @version $Revision$
* @author Roman Borschel
* @author Benjamin Eberlei
*/
class OnClearEventArgs extends \Doctrine\Common\EventArgs
{
/**
- * @var \Doctrine\ORM\EntityManager
+ * @var Doctrine\ORM\EntityManager
*/
private $em;
@@ -42,16 +41,21 @@ class OnClearEventArgs extends \Doctrine\Common\EventArgs
private $entityClass;
/**
- * @param \Doctrine\ORM\EntityManager $em
+ * Constructor.
+ *
+ * @param Doctrine\ORM\EntityManager $em
+ * @param string $entityClass Optional entity class
*/
public function __construct($em, $entityClass = null)
{
- $this->em = $em;
+ $this->em = $em;
$this->entityClass = $entityClass;
}
/**
- * @return \Doctrine\ORM\EntityManager
+ * Retrieve associated EntityManager.
+ *
+ * @return Doctrine\ORM\EntityManager
*/
public function getEntityManager()
{
@@ -75,6 +79,6 @@ class OnClearEventArgs extends \Doctrine\Common\EventArgs
*/
public function clearsAllEntities()
{
- return $this->entityClass === null;
+ return ($this->entityClass === null);
}
}
\ No newline at end of file
diff --git a/lib/Doctrine/ORM/Event/OnFlushEventArgs.php b/lib/Doctrine/ORM/Event/OnFlushEventArgs.php
index 1b4cb9ba8..5e6e839fe 100644
--- a/lib/Doctrine/ORM/Event/OnFlushEventArgs.php
+++ b/lib/Doctrine/ORM/Event/OnFlushEventArgs.php
@@ -21,37 +21,45 @@
namespace Doctrine\ORM\Event;
+use Doctrine\ORM\EntityManager;
+
/**
* Provides event arguments for the preFlush event.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
- * @link www.doctrine-project.com
+ * @link www.doctrine-project.org
* @since 2.0
- * @version $Revision$
* @author Roman Borschel
* @author Benjamin Eberlei
*/
class OnFlushEventArgs extends \Doctrine\Common\EventArgs
{
/**
- * @var EntityManager
+ * @var Doctirne\ORM\EntityManager
*/
- private $_em;
+ private $em;
- //private $_entitiesToPersist = array();
- //private $_entitiesToRemove = array();
+ //private $entitiesToPersist = array();
+ //private $entitiesToRemove = array();
- public function __construct($em)
+ /**
+ * Constructor.
+ *
+ * @param Doctrine\ORM\EntityManager $em
+ */
+ public function __construct(EntityManager $em)
{
- $this->_em = $em;
+ $this->em = $em;
}
/**
- * @return EntityManager
+ * Retrieve associated EntityManager.
+ *
+ * @return Doctrine\ORM\EntityManager
*/
public function getEntityManager()
{
- return $this->_em;
+ return $this->em;
}
/*
diff --git a/lib/Doctrine/ORM/Event/PostFlushEventArgs.php b/lib/Doctrine/ORM/Event/PostFlushEventArgs.php
index 92e88ae21..f500ad92f 100644
--- a/lib/Doctrine/ORM/Event/PostFlushEventArgs.php
+++ b/lib/Doctrine/ORM/Event/PostFlushEventArgs.php
@@ -17,9 +17,10 @@
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* .
-*/
+ */
namespace Doctrine\ORM\Event;
+
use Doctrine\ORM\EntityManager;
use Doctrine\Common\EventArgs;
@@ -27,20 +28,21 @@ use Doctrine\Common\EventArgs;
* Provides event arguments for the postFlush event.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
- * @link www.doctrine-project.com
+ * @link www.doctrine-project.org
* @since 2.0
- * @version $Revision$
* @author Daniel Freudenberger
*/
class PostFlushEventArgs extends EventArgs
{
/**
- * @var EntityManager
+ * @var Doctrine\ORM\EntityManager
*/
private $em;
/**
- * @param EntityManager $em
+ * Constructor.
+ *
+ * @param Doctrine\ORM\EntityManager $em
*/
public function __construct(EntityManager $em)
{
@@ -48,7 +50,9 @@ class PostFlushEventArgs extends EventArgs
}
/**
- * @return EntityManager
+ * Retrieve associated EntityManager.
+ *
+ * @return Doctrine\ORM\EntityManager
*/
public function getEntityManager()
{
diff --git a/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php b/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php
index ab1cc15de..35539591a 100644
--- a/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php
+++ b/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php
@@ -1,4 +1,23 @@
.
+ */
namespace Doctrine\ORM\Event;
@@ -8,42 +27,50 @@ use Doctrine\Common\EventArgs,
/**
* Class that holds event arguments for a preInsert/preUpdate event.
*
+ * @author Guilherme Blanco
* @author Roman Borschel
* @author Benjamin Eberlei
- * @since 2.0
+ * @since 2.0
*/
class PreUpdateEventArgs extends LifecycleEventArgs
{
/**
* @var array
*/
- private $_entityChangeSet;
+ private $entityChangeSet;
/**
- *
+ * Constructor.
+ *
* @param object $entity
- * @param EntityManager $em
+ * @param Doctrine\ORM\EntityManager $em
* @param array $changeSet
*/
- public function __construct($entity, $em, array &$changeSet)
+ public function __construct($entity, EntityManager $em, array &$changeSet)
{
parent::__construct($entity, $em);
- $this->_entityChangeSet = &$changeSet;
- }
-
- public function getEntityChangeSet()
- {
- return $this->_entityChangeSet;
+
+ $this->entityChangeSet = &$changeSet;
}
/**
- * Field has a changeset?
+ * Retrieve entity changeset.
+ *
+ * @return array
+ */
+ public function getEntityChangeSet()
+ {
+ return $this->entityChangeSet;
+ }
+
+ /**
+ * Check if field has a changeset.
*
- * @return bool
+ * @return boolean
*/
public function hasChangedField($field)
{
- return isset($this->_entityChangeSet[$field]);
+ return isset($this->entityChangeSet[$field]);
}
/**
@@ -54,9 +81,9 @@ class PreUpdateEventArgs extends LifecycleEventArgs
*/
public function getOldValue($field)
{
- $this->_assertValidField($field);
+ $this->assertValidField($field);
- return $this->_entityChangeSet[$field][0];
+ return $this->entityChangeSet[$field][0];
}
/**
@@ -67,9 +94,9 @@ class PreUpdateEventArgs extends LifecycleEventArgs
*/
public function getNewValue($field)
{
- $this->_assertValidField($field);
+ $this->assertValidField($field);
- return $this->_entityChangeSet[$field][1];
+ return $this->entityChangeSet[$field][1];
}
/**
@@ -80,18 +107,24 @@ class PreUpdateEventArgs extends LifecycleEventArgs
*/
public function setNewValue($field, $value)
{
- $this->_assertValidField($field);
+ $this->assertValidField($field);
- $this->_entityChangeSet[$field][1] = $value;
+ $this->entityChangeSet[$field][1] = $value;
}
- private function _assertValidField($field)
+ /**
+ * Assert the field exists in changeset.
+ *
+ * @param string $field
+ */
+ private function assertValidField($field)
{
- if (!isset($this->_entityChangeSet[$field])) {
- throw new \InvalidArgumentException(
- "Field '".$field."' is not a valid field of the entity ".
- "'".get_class($this->getEntity())."' in PreUpdateEventArgs."
- );
+ if ( ! isset($this->entityChangeSet[$field])) {
+ throw new \InvalidArgumentException(sprintf(
+ 'Field "%s" is not a valid field of the entity "%s" in PreUpdateEventArgs.',
+ $field,
+ get_class($this->getEntity())
+ ));
}
}
}
diff --git a/lib/Doctrine/ORM/Id/AssignedGenerator.php b/lib/Doctrine/ORM/Id/AssignedGenerator.php
index 90a35fa12..2e2d4f2f6 100644
--- a/lib/Doctrine/ORM/Id/AssignedGenerator.php
+++ b/lib/Doctrine/ORM/Id/AssignedGenerator.php
@@ -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;
}
}
diff --git a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php
index 1287a138b..5e0c9c0be 100644
--- a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php
+++ b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php
@@ -62,7 +62,7 @@ class ObjectHydrator extends AbstractHydrator
if (!isset($this->_hints['deferEagerLoad'])) {
$this->_hints['deferEagerLoad'] = true;
}
-
+
foreach ($this->_rsm->aliasMap as $dqlAlias => $className) {
$this->_identifierMap[$dqlAlias] = array();
$this->_idTemplate[$dqlAlias] = '';
@@ -116,13 +116,13 @@ class ObjectHydrator extends AbstractHydrator
protected function _cleanup()
{
$eagerLoad = (isset($this->_hints['deferEagerLoad'])) && $this->_hints['deferEagerLoad'] == true;
-
+
parent::_cleanup();
$this->_identifierMap =
$this->_initializedCollections =
$this->_existingCollections =
$this->_resultPointers = array();
-
+
if ($eagerLoad) {
$this->_em->getUnitOfWork()->triggerEagerLoads();
}
@@ -192,7 +192,7 @@ class ObjectHydrator extends AbstractHydrator
/**
* Gets an entity instance.
- *
+ *
* @param $data The instance data.
* @param $dqlAlias The DQL alias of the entity's class.
* @return object The entity.
@@ -205,12 +205,12 @@ class ObjectHydrator extends AbstractHydrator
$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);
}
-
+
return $this->_uow->createEntity($className, $data, $this->_hints);
}
@@ -240,7 +240,7 @@ class ObjectHydrator extends AbstractHydrator
* Gets a ClassMetadata instance from the local cache.
* If the instance is not yet in the local cache, it is loaded into the
* local cache.
- *
+ *
* @param string $className The name of the class.
* @return ClassMetadata
*/
@@ -254,21 +254,21 @@ class ObjectHydrator extends AbstractHydrator
/**
* Hydrates a single row in an SQL result set.
- *
+ *
* @internal
* First, the data of the row is split into chunks where each chunk contains data
* that belongs to a particular component/class. Afterwards, all these chunks
* are processed, one after the other. For each chunk of class data only one of the
* following code paths is executed:
- *
+ *
* Path A: The data chunk belongs to a joined/associated object and the association
* is collection-valued.
* Path B: The data chunk belongs to a joined/associated object and the association
* is single-valued.
* Path C: The data chunk belongs to a root result element/object that appears in the topmost
* level of the hydrated result. A typical example are the objects of the type
- * specified by the FROM clause in a DQL query.
- *
+ * specified by the FROM clause in a DQL query.
+ *
* @param array $data The data of the row to process.
* @param array $cache The cache to use.
* @param array $result The result array to fill.
@@ -369,10 +369,7 @@ class ObjectHydrator extends AbstractHydrator
$this->_resultPointers[$dqlAlias] = $reflFieldValue[$index];
}
} else if ( ! $reflField->getValue($parentObject)) {
- $coll = new PersistentCollection($this->_em, $this->_ce[$entityName], new ArrayCollection);
- $coll->setOwner($parentObject, $relation);
- $reflField->setValue($parentObject, $coll);
- $this->_uow->setOriginalEntityProperty($oid, $relationField, $coll);
+ $reflFieldValue = $this->_initRelatedCollection($parentObject, $parentClass, $relationField);
}
} else {
// PATH B: Single-valued association
diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
index 25a3350d2..10f7bc4b6 100644
--- a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
+++ b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
@@ -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.
*/
@@ -1904,6 +1904,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 +1950,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'];
}
/**
diff --git a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
index b676ca8da..fd6bf081a 100644
--- a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
+++ b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
@@ -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));
@@ -327,6 +327,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(" is not a valid tag");
}
$metadata->mapOneToMany($mapping);
@@ -432,8 +434,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(" is not a valid tag");
}
$metadata->mapManyToMany($mapping);
diff --git a/lib/Doctrine/ORM/NativeQuery.php b/lib/Doctrine/ORM/NativeQuery.php
index 2c0a5ab28..dea223fa3 100644
--- a/lib/Doctrine/ORM/NativeQuery.php
+++ b/lib/Doctrine/ORM/NativeQuery.php
@@ -57,17 +57,17 @@ final class NativeQuery extends AbstractQuery
*/
protected function _doExecute()
{
- $stmt = $this->_em->getConnection()->prepare($this->_sql);
$params = $this->_params;
- foreach ($params as $key => $value) {
- if (isset($this->_paramTypes[$key])) {
- $stmt->bindValue($key, $value, $this->_paramTypes[$key]);
- } else {
- $stmt->bindValue($key, $value);
+ $types = $this->_paramTypes;
+ if ($params) {
+ if (is_int(key($params))) {
+ ksort($params);
+ ksort($types);
+ $params = array_values($params);
+ $types = array_values($types);
}
}
- $stmt->execute();
- return $stmt;
+ return $this->_em->getConnection()->executeQuery($this->_sql, $params, $types, $this->_queryCacheProfile);
}
}
\ No newline at end of file
diff --git a/lib/Doctrine/ORM/PersistentCollection.php b/lib/Doctrine/ORM/PersistentCollection.php
index 82d616686..b64cacfdc 100644
--- a/lib/Doctrine/ORM/PersistentCollection.php
+++ b/lib/Doctrine/ORM/PersistentCollection.php
@@ -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);
diff --git a/lib/Doctrine/ORM/Persisters/AbstractEntityInheritancePersister.php b/lib/Doctrine/ORM/Persisters/AbstractEntityInheritancePersister.php
index 670cf11e7..84540a337 100644
--- a/lib/Doctrine/ORM/Persisters/AbstractEntityInheritancePersister.php
+++ b/lib/Doctrine/ORM/Persisters/AbstractEntityInheritancePersister.php
@@ -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;
}
-}
\ No newline at end of file
+}
diff --git a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php
index b747155b3..9d04cf5f1 100644
--- a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php
+++ b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php
@@ -92,7 +92,7 @@ class BasicEntityPersister
/**
* The database platform.
- *
+ *
* @var Doctrine\DBAL\Platforms\AbstractPlatform
*/
protected $_platform;
@@ -110,12 +110,12 @@ class BasicEntityPersister
* @var array
*/
protected $_queuedInserts = array();
-
+
/**
* ResultSetMapping that is used for all queries. Is generated lazily once per request.
- *
+ *
* TODO: Evaluate Caching in combination with the other cached SQL snippets.
- *
+ *
* @var Query\ResultSetMapping
*/
protected $_rsm;
@@ -123,7 +123,7 @@ class BasicEntityPersister
/**
* The map of column names to DBAL mapping types of all prepared columns used
* when INSERTing or UPDATEing an entity.
- *
+ *
* @var array
* @see _prepareInsertData($entity)
* @see _prepareUpdateData($entity)
@@ -133,7 +133,7 @@ class BasicEntityPersister
/**
* The INSERT SQL statement used for entities handled by this persister.
* This SQL is only generated once per request, if at all.
- *
+ *
* @var string
*/
private $_insertSql;
@@ -141,29 +141,29 @@ class BasicEntityPersister
/**
* The SELECT column list SQL fragment used for querying entities by this persister.
* This SQL fragment is only generated once per request, if at all.
- *
+ *
* @var string
*/
protected $_selectColumnListSql;
-
+
/**
* The JOIN SQL fragement used to eagerly load all many-to-one and one-to-one
* associations configured as FETCH_EAGER, aswell as all inverse one-to-one associations.
- *
+ *
* @var string
*/
protected $_selectJoinSql;
/**
* Counter for creating unique SQL table and column aliases.
- *
+ *
* @var integer
*/
protected $_sqlAliasCounter = 0;
/**
* Map from class names (FQCN) to the corresponding generated SQL table aliases.
- *
+ *
* @var array
*/
protected $_sqlTableAliases = array();
@@ -171,7 +171,7 @@ class BasicEntityPersister
/**
* Initializes a new BasicEntityPersister that uses the given EntityManager
* and persists instances of the class described by the given ClassMetadata descriptor.
- *
+ *
* @param Doctrine\ORM\EntityManager $em
* @param Doctrine\ORM\Mapping\ClassMetadata $class
*/
@@ -205,7 +205,7 @@ class BasicEntityPersister
/**
* Executes all queued entity insertions and returns any generated post-insert
* identifiers that were created as a result of the insertions.
- *
+ *
* If no inserts are queued, invoking this method is a NOOP.
*
* @return array An array of any generated post-insert IDs. This will be an empty array
@@ -229,7 +229,7 @@ class BasicEntityPersister
if (isset($insertData[$tableName])) {
$paramIndex = 1;
-
+
foreach ($insertData[$tableName] as $column => $value) {
$stmt->bindValue($paramIndex++, $value, $this->_columnTypes[$column]);
}
@@ -257,7 +257,7 @@ class BasicEntityPersister
/**
* Retrieves the default version value which was created
- * by the preceding INSERT statement and assigns it back in to the
+ * by the preceding INSERT statement and assigns it back in to the
* entities version field.
*
* @param object $entity
@@ -271,7 +271,7 @@ class BasicEntityPersister
/**
* Fetch the current version value of a versioned entity.
- *
+ *
* @param Doctrine\ORM\Mapping\ClassMetadata $versionedClass
* @param mixed $id
* @return mixed
@@ -280,9 +280,9 @@ class BasicEntityPersister
{
$versionField = $versionedClass->versionField;
$identifier = $versionedClass->getIdentifierColumnNames();
-
+
$versionFieldColumnName = $versionedClass->getQuotedColumnName($versionField, $this->_platform);
-
+
//FIXME: Order with composite keys might not be correct
$sql = 'SELECT ' . $versionFieldColumnName
. ' FROM ' . $versionedClass->getQuotedTableName($this->_platform)
@@ -299,7 +299,7 @@ class BasicEntityPersister
* The data to update is retrieved through {@link _prepareUpdateData}.
* Subclasses that override this method are supposed to obtain the update data
* in the same way, through {@link _prepareUpdateData}.
- *
+ *
* Subclasses are also supposed to take care of versioning when overriding this method,
* if necessary. The {@link _updateTable} method can be used to apply the data retrieved
* from {@_prepareUpdateData} on the target tables, thereby optionally applying versioning.
@@ -310,7 +310,7 @@ class BasicEntityPersister
{
$updateData = $this->_prepareUpdateData($entity);
$tableName = $this->_class->getTableName();
-
+
if (isset($updateData[$tableName]) && $updateData[$tableName]) {
$this->_updateTable(
$entity, $this->_class->getQuotedTableName($this->_platform),
@@ -338,17 +338,17 @@ class BasicEntityPersister
$set = $params = $types = array();
foreach ($updateData as $columnName => $value) {
- $set[] = (isset($this->_class->fieldNames[$columnName]))
+ $set[] = (isset($this->_class->fieldNames[$columnName]))
? $this->_class->getQuotedColumnName($this->_class->fieldNames[$columnName], $this->_platform) . ' = ?'
: $columnName . ' = ?';
-
+
$params[] = $value;
$types[] = $this->_columnTypes[$columnName];
}
$where = array();
$id = $this->_em->getUnitOfWork()->getEntityIdentifier($entity);
-
+
foreach ($this->_class->identifier as $idField) {
if (isset($this->_class->associationMappings[$idField])) {
$targetMapping = $this->_em->getClassMetadata($this->_class->associationMappings[$idField]['targetEntity']);
@@ -366,13 +366,13 @@ class BasicEntityPersister
$versionField = $this->_class->versionField;
$versionFieldType = $this->_class->fieldMappings[$versionField]['type'];
$versionColumn = $this->_class->getQuotedColumnName($versionField, $this->_platform);
-
+
if ($versionFieldType == Type::INTEGER) {
$set[] = $versionColumn . ' = ' . $versionColumn . ' + 1';
} else if ($versionFieldType == Type::DATETIME) {
$set[] = $versionColumn . ' = CURRENT_TIMESTAMP';
}
-
+
$where[] = $versionColumn;
$params[] = $this->_class->reflFields[$versionField]->getValue($entity);
$types[] = $this->_class->fieldMappings[$versionField]['type'];
@@ -401,18 +401,18 @@ class BasicEntityPersister
// @Todo this only covers scenarios with no inheritance or of the same level. Is there something
// like self-referential relationship between different levels of an inheritance hierachy? I hope not!
$selfReferential = ($mapping['targetEntity'] == $mapping['sourceEntity']);
-
+
if ( ! $mapping['isOwningSide']) {
$relatedClass = $this->_em->getClassMetadata($mapping['targetEntity']);
$mapping = $relatedClass->associationMappings[$mapping['mappedBy']];
$keys = array_keys($mapping['relationToTargetKeyColumns']);
-
+
if ($selfReferential) {
$otherKeys = array_keys($mapping['relationToSourceKeyColumns']);
}
} else {
$keys = array_keys($mapping['relationToSourceKeyColumns']);
-
+
if ($selfReferential) {
$otherKeys = array_keys($mapping['relationToTargetKeyColumns']);
}
@@ -420,13 +420,13 @@ class BasicEntityPersister
if ( ! isset($mapping['isOnDeleteCascade'])) {
$this->_conn->delete(
- $this->_class->getQuotedJoinTableName($mapping, $this->_platform),
+ $this->_class->getQuotedJoinTableName($mapping, $this->_platform),
array_combine($keys, $identifier)
);
if ($selfReferential) {
$this->_conn->delete(
- $this->_class->getQuotedJoinTableName($mapping, $this->_platform),
+ $this->_class->getQuotedJoinTableName($mapping, $this->_platform),
array_combine($otherKeys, $identifier)
);
}
@@ -458,7 +458,7 @@ class BasicEntityPersister
* Prepares the changeset of an entity for database insertion (UPDATE).
*
* The changeset is obtained from the currently running UnitOfWork.
- *
+ *
* During this preparation the array that is passed as the second parameter is filled with
* => pairs, grouped by table name.
*
@@ -493,7 +493,7 @@ class BasicEntityPersister
if (isset($this->_class->associationMappings[$field])) {
$assoc = $this->_class->associationMappings[$field];
-
+
// Only owning side of x-1 associations can have a FK column.
if ( ! $assoc['isOwningSide'] || ! ($assoc['type'] & ClassMetadata::TO_ONE)) {
continue;
@@ -501,7 +501,7 @@ class BasicEntityPersister
if ($newVal !== null) {
$oid = spl_object_hash($newVal);
-
+
if (isset($this->_queuedInserts[$oid]) || $uow->isScheduledForInsert($newVal)) {
// The associated entity $newVal is not yet persisted, so we must
// set $newVal = null, in order to insert a null value and schedule an
@@ -528,7 +528,7 @@ class BasicEntityPersister
} else {
$result[$owningTable][$sourceColumn] = $newValId[$targetClass->fieldNames[$targetColumn]];
}
-
+
$this->_columnTypes[$sourceColumn] = $targetClass->getTypeOfColumn($targetColumn);
}
} else {
@@ -537,7 +537,7 @@ class BasicEntityPersister
$result[$this->getOwningTable($field)][$columnName] = $newVal;
}
}
-
+
return $result;
}
@@ -589,7 +589,7 @@ class BasicEntityPersister
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc, $lockMode, $limit);
list($params, $types) = $this->expandParameters($criteria);
$stmt = $this->_conn->executeQuery($sql, $params, $types);
-
+
if ($entity !== null) {
$hints[Query::HINT_REFRESH] = true;
$hints[Query::HINT_REFRESH_ENTITY] = $entity;
@@ -597,7 +597,7 @@ class BasicEntityPersister
$hydrator = $this->_em->newHydrator($this->_selectJoinSql ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT);
$entities = $hydrator->hydrateAll($stmt, $this->_rsm, $hints);
-
+
return $entities ? $entities[0] : null;
}
@@ -626,17 +626,17 @@ class BasicEntityPersister
// Mark inverse side as fetched in the hints, otherwise the UoW would
// try to load it in a separate query (remember: to-one inverse sides can not be lazy).
$hints = array();
-
+
if ($isInverseSingleValued) {
$hints['fetched'][$targetClass->name][$assoc['inversedBy']] = true;
-
+
if ($targetClass->subClasses) {
foreach ($targetClass->subClasses as $targetSubclassName) {
$hints['fetched'][$targetSubclassName][$assoc['inversedBy']] = true;
}
}
}
-
+
/* cascade read-only status
if ($this->_em->getUnitOfWork()->isReadOnly($sourceEntity)) {
$hints[Query::HINT_READ_ONLY] = true;
@@ -652,7 +652,7 @@ class BasicEntityPersister
} else {
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
$owningAssoc = $targetClass->getAssociationMapping($assoc['mappedBy']);
-
+
// TRICKY: since the association is specular source and target are flipped
foreach ($owningAssoc['targetToSourceKeyColumns'] as $sourceKeyColumn => $targetKeyColumn) {
if ( ! isset($sourceClass->fieldNames[$sourceKeyColumn])) {
@@ -660,12 +660,12 @@ class BasicEntityPersister
$sourceClass->name, $sourceKeyColumn
);
}
-
+
// unset the old value and set the new sql aliased value here. By definition
// unset($identifier[$targetKeyColumn] works here with how UnitOfWork::createEntity() calls this method.
$identifier[$this->_getSQLTableAlias($targetClass->name) . "." . $targetKeyColumn] =
$sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
-
+
unset($identifier[$targetKeyColumn]);
}
@@ -681,7 +681,7 @@ class BasicEntityPersister
/**
* Refreshes a managed entity.
- *
+ *
* @param array $id The identifier of the entity as an associative array from
* column or field names to values.
* @param object $entity The entity to refresh.
@@ -691,16 +691,16 @@ class BasicEntityPersister
$sql = $this->_getSelectEntitiesSQL($id);
list($params, $types) = $this->expandParameters($id);
$stmt = $this->_conn->executeQuery($sql, $params, $types);
-
+
$hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT);
$hydrator->hydrateAll($stmt, $this->_rsm, array(Query::HINT_REFRESH => true));
if (isset($this->_class->lifecycleCallbacks[Events::postLoad])) {
$this->_class->invokeLifecycleCallbacks(Events::postLoad, $entity);
}
-
+
$evm = $this->_em->getEventManager();
-
+
if ($evm->hasListeners(Events::postLoad)) {
$evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity, $this->_em));
}
@@ -708,7 +708,7 @@ class BasicEntityPersister
/**
* Loads a list of entities by a list of field criteria.
- *
+ *
* @param array $criteria
* @param array $orderBy
* @param int $limit
@@ -723,13 +723,13 @@ class BasicEntityPersister
$stmt = $this->_conn->executeQuery($sql, $params, $types);
$hydrator = $this->_em->newHydrator(($this->_selectJoinSql) ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT);
-
+
return $hydrator->hydrateAll($stmt, $this->_rsm, array('deferEagerLoads' => true));
}
/**
* Get (sliced or full) elements of the given collection.
- *
+ *
* @param array $assoc
* @param object $sourceEntity
* @param int|null $offset
@@ -739,16 +739,16 @@ class BasicEntityPersister
public function getManyToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null)
{
$stmt = $this->getManyToManyStatement($assoc, $sourceEntity, $offset, $limit);
-
+
return $this->loadArrayFromStatement($assoc, $stmt);
}
/**
* Load an array of entities from a given dbal statement.
- *
+ *
* @param array $assoc
* @param Doctrine\DBAL\Statement $stmt
- *
+ *
* @return array
*/
private function loadArrayFromStatement($assoc, $stmt)
@@ -763,21 +763,21 @@ class BasicEntityPersister
}
$hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT);
-
+
return $hydrator->hydrateAll($stmt, $rsm, $hints);
}
/**
* Hydrate a collection from a given dbal statement.
- *
+ *
* @param array $assoc
* @param Doctrine\DBAL\Statement $stmt
* @param PersistentCollection $coll
- *
+ *
* @return array
*/
private function loadCollectionFromStatement($assoc, $stmt, $coll)
- {
+ {
$hints = array('deferEagerLoads' => true, 'collection' => $coll);
if (isset($assoc['indexBy'])) {
@@ -788,7 +788,7 @@ class BasicEntityPersister
}
$hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT);
-
+
return $hydrator->hydrateAll($stmt, $rsm, $hints);
}
@@ -805,7 +805,7 @@ class BasicEntityPersister
public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
{
$stmt = $this->getManyToManyStatement($assoc, $sourceEntity);
-
+
return $this->loadCollectionFromStatement($assoc, $stmt, $coll);
}
@@ -813,15 +813,15 @@ class BasicEntityPersister
{
$criteria = array();
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
-
+
if ($assoc['isOwningSide']) {
$quotedJoinTable = $sourceClass->getQuotedJoinTableName($assoc, $this->_platform);
-
+
foreach ($assoc['relationToSourceKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
if ($sourceClass->containsForeignIdentifier) {
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
-
+
if (isset($sourceClass->associationMappings[$field])) {
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
$value = $value[$this->_em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]];
@@ -839,18 +839,18 @@ class BasicEntityPersister
} else {
$owningAssoc = $this->_em->getClassMetadata($assoc['targetEntity'])->associationMappings[$assoc['mappedBy']];
$quotedJoinTable = $sourceClass->getQuotedJoinTableName($owningAssoc, $this->_platform);
-
+
// TRICKY: since the association is inverted source and target are flipped
foreach ($owningAssoc['relationToTargetKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
if ($sourceClass->containsForeignIdentifier) {
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
-
+
if (isset($sourceClass->associationMappings[$field])) {
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
$value = $value[$this->_em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]];
}
-
+
$criteria[$quotedJoinTable . "." . $relationKeyColumn] = $value;
} else if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
$criteria[$quotedJoinTable . "." . $relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
@@ -864,7 +864,7 @@ class BasicEntityPersister
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc, 0, $limit, $offset);
list($params, $types) = $this->expandParameters($criteria);
-
+
return $this->_conn->executeQuery($sql, $params, $types);
}
@@ -890,7 +890,7 @@ class BasicEntityPersister
$orderBySql = $orderBy ? $this->_getOrderBySQL($orderBy, $this->_getSQLTableAlias($this->_class->name)) : '';
$lockSql = '';
-
+
if ($lockMode == LockMode::PESSIMISTIC_READ) {
$lockSql = ' ' . $this->_platform->getReadLockSql();
} else if ($lockMode == LockMode::PESSIMISTIC_WRITE) {
@@ -908,7 +908,7 @@ class BasicEntityPersister
/**
* Gets the ORDER BY SQL snippet for ordered collections.
- *
+ *
* @param array $orderBy
* @param string $baseTableAlias
* @return string
@@ -917,7 +917,7 @@ class BasicEntityPersister
protected final function _getOrderBySQL(array $orderBy, $baseTableAlias)
{
$orderBySql = '';
-
+
foreach ($orderBy as $fieldName => $orientation) {
if ( ! isset($this->_class->fieldMappings[$fieldName])) {
throw ORMException::unrecognizedField($fieldName);
@@ -928,7 +928,7 @@ class BasicEntityPersister
: $baseTableAlias;
$columnName = $this->_class->getQuotedColumnName($fieldName, $this->_platform);
-
+
$orderBySql .= $orderBySql ? ', ' : ' ORDER BY ';
$orderBySql .= $tableAlias . '.' . $columnName . ' ' . $orientation;
}
@@ -944,7 +944,7 @@ class BasicEntityPersister
* list SQL fragment. Note that in the implementation of BasicEntityPersister
* the resulting SQL fragment is generated only once and cached in {@link _selectColumnListSql}.
* Subclasses may or may not do the same.
- *
+ *
* @return string The SQL fragment.
* @todo Rename: _getSelectColumnsSQL()
*/
@@ -961,58 +961,56 @@ class BasicEntityPersister
// Add regular columns to select list
foreach ($this->_class->fieldNames as $field) {
if ($columnList) $columnList .= ', ';
-
+
$columnList .= $this->_getSelectColumnSQL($field, $this->_class);
}
$this->_selectJoinSql = '';
$eagerAliasCounter = 0;
-
+
foreach ($this->_class->associationMappings as $assocField => $assoc) {
$assocColumnSQL = $this->_getSelectColumnAssociationSQL($assocField, $assoc, $this->_class);
-
+
if ($assocColumnSQL) {
if ($columnList) $columnList .= ', ';
-
+
$columnList .= $assocColumnSQL;
}
-
+
if ($assoc['type'] & ClassMetadata::TO_ONE && ($assoc['fetch'] == ClassMetadata::FETCH_EAGER || !$assoc['isOwningSide'])) {
$eagerEntity = $this->_em->getClassMetadata($assoc['targetEntity']);
-
+
if ($eagerEntity->inheritanceType != ClassMetadata::INHERITANCE_TYPE_NONE) {
continue; // now this is why you shouldn't use inheritance
}
-
+
$assocAlias = 'e' . ($eagerAliasCounter++);
$this->_rsm->addJoinedEntityResult($assoc['targetEntity'], $assocAlias, 'r', $assocField);
-
+
foreach ($eagerEntity->fieldNames AS $field) {
if ($columnList) $columnList .= ', ';
-
+
$columnList .= $this->_getSelectColumnSQL($field, $eagerEntity, $assocAlias);
}
-
+
foreach ($eagerEntity->associationMappings as $assoc2Field => $assoc2) {
$assoc2ColumnSQL = $this->_getSelectColumnAssociationSQL($assoc2Field, $assoc2, $eagerEntity, $assocAlias);
-
+
if ($assoc2ColumnSQL) {
if ($columnList) $columnList .= ', ';
$columnList .= $assoc2ColumnSQL;
}
}
-
$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;
$first = false;
@@ -1029,8 +1027,8 @@ class BasicEntityPersister
if ( ! $first) {
$this->_selectJoinSql .= ' AND ';
}
-
- $this->_selectJoinSql .= $this->_getSQLTableAlias($owningAssoc['sourceEntity'], $assocAlias) . '.' . $sourceCol . ' = '
+
+ $this->_selectJoinSql .= $this->_getSQLTableAlias($owningAssoc['sourceEntity'], $assocAlias) . '.' . $sourceCol . ' = '
. $this->_getSQLTableAlias($owningAssoc['targetEntity']) . '.' . $targetCol;
$first = false;
}
@@ -1042,33 +1040,32 @@ class BasicEntityPersister
return $this->_selectColumnListSql;
}
-
+
/**
* Gets the SQL join fragment used when selecting entities from an association.
- *
+ *
* @param string $field
* @param array $assoc
* @param ClassMetadata $class
* @param string $alias
- *
- * @return string
+ *
+ * @return string
*/
protected function _getSelectColumnAssociationSQL($field, $assoc, ClassMetadata $class, $alias = 'r')
{
$columnList = '';
-
+
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
if ($columnList) $columnList .= ', ';
- $columnAlias = $srcColumn . $this->_sqlAliasCounter++;
- $resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
+ $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);
}
}
-
+
return $columnList;
}
@@ -1088,10 +1085,10 @@ class BasicEntityPersister
$owningAssoc = $this->_em->getClassMetadata($manyToMany['targetEntity'])->associationMappings[$manyToMany['mappedBy']];
$joinClauses = $owningAssoc['relationToSourceKeyColumns'];
}
-
+
$joinTableName = $this->_class->getQuotedJoinTableName($owningAssoc, $this->_platform);
$joinSql = '';
-
+
foreach ($joinClauses as $joinTableColumn => $sourceColumn) {
if ($joinSql != '') $joinSql .= ' AND ';
@@ -1110,7 +1107,7 @@ class BasicEntityPersister
/**
* Gets the INSERT SQL used by the persister to persist a new entity.
- *
+ *
* @return string
*/
protected function _getInsertSQL()
@@ -1118,7 +1115,7 @@ class BasicEntityPersister
if ($this->_insertSql === null) {
$insertSql = '';
$columns = $this->_getInsertColumnList();
-
+
if (empty($columns)) {
$insertSql = $this->_platform->getEmptyIdentityInsertSQL(
$this->_class->getQuotedTableName($this->_platform),
@@ -1131,10 +1128,10 @@ class BasicEntityPersister
$insertSql = 'INSERT INTO ' . $this->_class->getQuotedTableName($this->_platform)
. ' (' . implode(', ', $columns) . ') VALUES (' . implode(', ', $values) . ')';
}
-
+
$this->_insertSql = $insertSql;
}
-
+
return $this->_insertSql;
}
@@ -1149,15 +1146,15 @@ class BasicEntityPersister
protected function _getInsertColumnList()
{
$columns = array();
-
+
foreach ($this->_class->reflFields as $name => $field) {
if ($this->_class->isVersioned && $this->_class->versionField == $name) {
continue;
}
-
+
if (isset($this->_class->associationMappings[$name])) {
$assoc = $this->_class->associationMappings[$name];
-
+
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
foreach ($assoc['targetToSourceKeyColumns'] as $sourceCol) {
$columns[] = $sourceCol;
@@ -1181,11 +1178,10 @@ class BasicEntityPersister
*/
protected function _getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r')
{
- $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($class->columnNames[$field]);
+
$this->_rsm->addFieldResult($alias, $columnAlias, $field);
return $sql . ' AS ' . $columnAlias;
@@ -1193,7 +1189,7 @@ class BasicEntityPersister
/**
* Gets the SQL table alias for the given class name.
- *
+ *
* @param string $className
* @return string The SQL table alias.
* @todo Reconsider. Binding table aliases to class names is not such a good idea.
@@ -1203,15 +1199,15 @@ class BasicEntityPersister
if ($assocName) {
$className .= '#' . $assocName;
}
-
+
if (isset($this->_sqlTableAliases[$className])) {
return $this->_sqlTableAliases[$className];
}
-
+
$tableAlias = 't' . $this->_sqlAliasCounter++;
$this->_sqlTableAliases[$className] = $tableAlias;
-
+
return $tableAlias;
}
@@ -1235,9 +1231,9 @@ class BasicEntityPersister
$sql = 'SELECT 1 '
. $this->_platform->appendLockHint($this->getLockTablesSql(), $lockMode)
. ($conditionSql ? ' WHERE ' . $conditionSql : '') . ' ' . $lockSql;
-
+
list($params, $types) = $this->expandParameters($criteria);
-
+
$stmt = $this->_conn->executeQuery($sql, $params, $types);
}
@@ -1266,25 +1262,25 @@ class BasicEntityPersister
protected function _getSelectConditionSQL(array $criteria, $assoc = null)
{
$conditionSql = '';
-
+
foreach ($criteria as $field => $value) {
$conditionSql .= $conditionSql ? ' AND ' : '';
if (isset($this->_class->columnNames[$field])) {
$className = (isset($this->_class->fieldMappings[$field]['inherited']))
- ? $this->_class->fieldMappings[$field]['inherited']
+ ? $this->_class->fieldMappings[$field]['inherited']
: $this->_class->name;
-
+
$conditionSql .= $this->_getSQLTableAlias($className) . '.' . $this->_class->getQuotedColumnName($field, $this->_platform);
} else if (isset($this->_class->associationMappings[$field])) {
if ( ! $this->_class->associationMappings[$field]['isOwningSide']) {
throw ORMException::invalidFindByInverseAssociation($this->_class->name, $field);
}
-
+
$className = (isset($this->_class->associationMappings[$field]['inherited']))
? $this->_class->associationMappings[$field]['inherited']
: $this->_class->name;
-
+
$conditionSql .= $this->_getSQLTableAlias($className) . '.' . $this->_class->associationMappings[$field]['joinColumns'][0]['name'];
} else if ($assoc !== null && strpos($field, " ") === false && strpos($field, "(") === false) {
// very careless developers could potentially open up this normally hidden api for userland attacks,
@@ -1295,7 +1291,7 @@ class BasicEntityPersister
} else {
throw ORMException::unrecognizedField($field);
}
-
+
$conditionSql .= (is_array($value)) ? ' IN (?)' : (($value === null) ? ' IS NULL' : ' = ?');
}
return $conditionSql;
@@ -1313,7 +1309,7 @@ class BasicEntityPersister
public function getOneToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null)
{
$stmt = $this->getOneToManyStatement($assoc, $sourceEntity, $offset, $limit);
-
+
return $this->loadArrayFromStatement($assoc, $stmt);
}
@@ -1329,7 +1325,7 @@ class BasicEntityPersister
public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
{
$stmt = $this->getOneToManyStatement($assoc, $sourceEntity);
-
+
return $this->loadCollectionFromStatement($assoc, $stmt, $coll);
}
@@ -1354,12 +1350,12 @@ class BasicEntityPersister
if ($sourceClass->containsForeignIdentifier) {
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
-
+
if (isset($sourceClass->associationMappings[$field])) {
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
$value = $value[$this->_em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]];
}
-
+
$criteria[$tableAlias . "." . $targetKeyColumn] = $value;
} else {
$criteria[$tableAlias . "." . $targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
@@ -1390,13 +1386,13 @@ class BasicEntityPersister
$types[] = $this->getType($field, $value);
$params[] = $this->getValue($value);
}
-
+
return array($params, $types);
}
-
+
/**
* Infer field type to be used by parameter type casting.
- *
+ *
* @param string $field
* @param mixed $value
* @return integer
@@ -1410,11 +1406,11 @@ class BasicEntityPersister
case (isset($this->_class->associationMappings[$field])):
$assoc = $this->_class->associationMappings[$field];
-
+
if (count($assoc['sourceToTargetKeyColumns']) > 1) {
throw Query\QueryException::associationPathCompositeKeyNotSupported();
}
-
+
$targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
$targetColumn = $assoc['joinColumns'][0]['referencedColumnName'];
$type = null;
@@ -1432,36 +1428,36 @@ class BasicEntityPersister
if (is_array($value)) {
$type += Connection::ARRAY_PARAM_OFFSET;
}
-
+
return $type;
}
-
+
/**
* Retrieve parameter value
- *
+ *
* @param mixed $value
- * @return mixed
+ * @return mixed
*/
private function getValue($value)
{
if (is_array($value)) {
$newValue = array();
-
+
foreach ($value as $itemValue) {
$newValue[] = $this->getIndividualValue($itemValue);
}
-
+
return $newValue;
}
-
+
return $this->getIndividualValue($value);
}
-
+
/**
* Retrieve an invidiual parameter value
- *
+ *
* @param mixed $value
- * @return mixed
+ * @return mixed
*/
private function getIndividualValue($value)
{
@@ -1472,11 +1468,11 @@ class BasicEntityPersister
$class = $this->_em->getClassMetadata(get_class($value));
$idValues = $class->getIdentifierValues($value);
}
-
+
$value = $idValues[key($idValues)];
}
-
- return $value;
+
+ return $value;
}
/**
@@ -1488,17 +1484,17 @@ class BasicEntityPersister
public function exists($entity, array $extraConditions = array())
{
$criteria = $this->_class->getIdentifierValues($entity);
-
+
if ($extraConditions) {
$criteria = array_merge($criteria, $extraConditions);
}
- $sql = 'SELECT 1'
- . ' FROM ' . $this->_class->getQuotedTableName($this->_platform) . ' ' . $this->_getSQLTableAlias($this->_class->name)
+ $sql = 'SELECT 1 '
+ . $this->getLockTablesSql()
. ' WHERE ' . $this->_getSelectConditionSQL($criteria);
-
+
list($params, $types) = $this->expandParameters($criteria);
-
+
return (bool) $this->_conn->fetchColumn($sql, $params);
}
@@ -1519,4 +1515,19 @@ class BasicEntityPersister
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())
+ );
+ }
}
diff --git a/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php b/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php
index c95fee755..fb60d5e32 100644
--- a/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php
+++ b/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php
@@ -46,7 +46,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
/**
* Map of table to quoted table names.
- *
+ *
* @var array
*/
private $_quotedTableMap = array();
@@ -59,7 +59,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
$class = ($this->_class->name !== $this->_class->rootEntityName)
? $this->_em->getClassMetadata($this->_class->rootEntityName)
: $this->_class;
-
+
return $class->getTableName();
}
@@ -73,10 +73,10 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
{
if (isset($this->_class->fieldMappings[$this->_class->versionField]['inherited'])) {
$definingClassName = $this->_class->fieldMappings[$this->_class->versionField]['inherited'];
-
+
return $this->_em->getClassMetadata($definingClassName);
}
-
+
return $this->_class;
}
@@ -92,7 +92,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
if (isset($this->_owningTableMap[$fieldName])) {
return $this->_owningTableMap[$fieldName];
}
-
+
if (isset($this->_class->associationMappings[$fieldName]['inherited'])) {
$cm = $this->_em->getClassMetadata($this->_class->associationMappings[$fieldName]['inherited']);
} else if (isset($this->_class->fieldMappings[$fieldName]['inherited'])) {
@@ -130,15 +130,15 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
// Prepare statements for sub tables.
$subTableStmts = array();
-
+
if ($rootClass !== $this->_class) {
$subTableStmts[$this->_class->getTableName()] = $this->_conn->prepare($this->_getInsertSQL());
}
-
+
foreach ($this->_class->parentClasses as $parentClassName) {
$parentClass = $this->_em->getClassMetadata($parentClassName);
$parentTableName = $parentClass->getTableName();
-
+
if ($parentClass !== $rootClass) {
$parentPersister = $this->_em->getUnitOfWork()->getEntityPersister($parentClassName);
$subTableStmts[$parentTableName] = $this->_conn->prepare($parentPersister->_getInsertSQL());
@@ -153,11 +153,11 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
// Execute insert on root table
$paramIndex = 1;
-
+
foreach ($insertData[$rootTableName] as $columnName => $value) {
$rootTableStmt->bindValue($paramIndex++, $value, $this->_columnTypes[$columnName]);
}
-
+
$rootTableStmt->execute();
if ($isPostInsertId) {
@@ -172,23 +172,23 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
foreach ($subTableStmts as $tableName => $stmt) {
$data = isset($insertData[$tableName]) ? $insertData[$tableName] : array();
$paramIndex = 1;
-
+
foreach ((array) $id as $idName => $idVal) {
$type = isset($this->_columnTypes[$idName]) ? $this->_columnTypes[$idName] : Type::STRING;
-
+
$stmt->bindValue($paramIndex++, $idVal, $type);
}
-
+
foreach ($data as $columnName => $value) {
$stmt->bindValue($paramIndex++, $value, $this->_columnTypes[$columnName]);
}
-
+
$stmt->execute();
}
}
$rootTableStmt->closeCursor();
-
+
foreach ($subTableStmts as $stmt) {
$stmt->closeCursor();
}
@@ -220,7 +220,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
$entity, $this->_quotedTableMap[$tableName], $data, $isVersioned && $versionedTable == $tableName
);
}
-
+
// Make sure the table with the version column is updated even if no columns on that
// table were affected.
if ($isVersioned && ! isset($updateData[$versionedTable])) {
@@ -251,7 +251,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
} else {
// Delete from all tables individually, starting from this class' table up to the root table.
$this->_conn->delete($this->_class->getQuotedTableName($this->_platform), $id);
-
+
foreach ($this->_class->parentClasses as $parentClass) {
$this->_conn->delete(
$this->_em->getClassMetadata($parentClass)->getQuotedTableName($this->_platform), $id
@@ -270,16 +270,16 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
// Create the column list fragment only once
if ($this->_selectColumnListSql === null) {
-
+
$this->_rsm = new ResultSetMapping();
$this->_rsm->addEntityResult($this->_class->name, 'r');
-
+
// Add regular columns
$columnList = '';
-
+
foreach ($this->_class->fieldMappings as $fieldName => $mapping) {
if ($columnList != '') $columnList .= ', ';
-
+
$columnList .= $this->_getSelectColumnSQL(
$fieldName,
isset($mapping['inherited']) ? $this->_em->getClassMetadata($mapping['inherited']) : $this->_class
@@ -290,12 +290,12 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
foreach ($this->_class->associationMappings as $assoc2) {
if ($assoc2['isOwningSide'] && $assoc2['type'] & ClassMetadata::TO_ONE) {
$tableAlias = isset($assoc2['inherited']) ? $this->_getSQLTableAlias($assoc2['inherited']) : $baseTableAlias;
-
+
foreach ($assoc2['targetToSourceKeyColumns'] as $srcColumn) {
if ($columnList != '') $columnList .= ', ';
-
+
$columnList .= $this->getSelectJoinColumnSQL(
- $tableAlias,
+ $tableAlias,
$srcColumn,
isset($assoc2['inherited']) ? $assoc2['inherited'] : $this->_class->name
);
@@ -309,23 +309,23 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
$columnList .= ', ' . $tableAlias . '.' . $discrColumn;
$resultColumnName = $this->_platform->getSQLResultCasing($discrColumn);
-
+
$this->_rsm->setDiscriminatorColumn('r', $resultColumnName);
$this->_rsm->addMetaResult('r', $resultColumnName, $discrColumn);
}
// INNER JOIN parent tables
$joinSql = '';
-
+
foreach ($this->_class->parentClasses as $parentClassName) {
$parentClass = $this->_em->getClassMetadata($parentClassName);
$tableAlias = $this->_getSQLTableAlias($parentClassName);
$joinSql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
$first = true;
-
+
foreach ($idColumns as $idColumn) {
if ($first) $first = false; else $joinSql .= ' AND ';
-
+
$joinSql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
}
}
@@ -339,7 +339,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
// Add subclass columns
foreach ($subClass->fieldMappings as $fieldName => $mapping) {
if (isset($mapping['inherited'])) continue;
-
+
$columnList .= ', ' . $this->_getSelectColumnSQL($fieldName, $subClass);
}
@@ -348,9 +348,9 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
if ($assoc2['isOwningSide'] && $assoc2['type'] & ClassMetadata::TO_ONE && ! isset($assoc2['inherited'])) {
foreach ($assoc2['targetToSourceKeyColumns'] as $srcColumn) {
if ($columnList != '') $columnList .= ', ';
-
+
$columnList .= $this->getSelectJoinColumnSQL(
- $tableAlias,
+ $tableAlias,
$srcColumn,
isset($assoc2['inherited']) ? $assoc2['inherited'] : $subClass->name
);
@@ -362,10 +362,10 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
// Add LEFT JOIN
$joinSql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
$first = true;
-
+
foreach ($idColumns as $idColumn) {
if ($first) $first = false; else $joinSql .= ' AND ';
-
+
$joinSql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
}
}
@@ -382,7 +382,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
}
$lockSql = '';
-
+
if ($lockMode == LockMode::PESSIMISTIC_READ) {
$lockSql = ' ' . $this->_platform->getReadLockSql();
} else if ($lockMode == LockMode::PESSIMISTIC_WRITE) {
@@ -408,29 +408,29 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
// INNER JOIN parent tables
$joinSql = '';
-
+
foreach ($this->_class->parentClasses as $parentClassName) {
$parentClass = $this->_em->getClassMetadata($parentClassName);
$tableAlias = $this->_getSQLTableAlias($parentClassName);
$joinSql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
$first = true;
-
+
foreach ($idColumns as $idColumn) {
if ($first) $first = false; else $joinSql .= ' AND ';
-
+
$joinSql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
}
}
return 'FROM ' . $this->_class->getQuotedTableName($this->_platform) . ' ' . $baseTableAlias . $joinSql;
}
-
+
/* Ensure this method is never called. This persister overrides _getSelectEntitiesSQL directly. */
protected function _getSelectColumnListSQL()
{
throw new \BadMethodCallException("Illegal invocation of ".__METHOD__.".");
}
-
+
/** {@inheritdoc} */
protected function _getInsertColumnList()
{
diff --git a/lib/Doctrine/ORM/Query.php b/lib/Doctrine/ORM/Query.php
index e0bbcec5a..ac1eb75d7 100644
--- a/lib/Doctrine/ORM/Query.php
+++ b/lib/Doctrine/ORM/Query.php
@@ -232,6 +232,9 @@ final class Query extends AbstractQuery
protected function _doExecute()
{
$executor = $this->_parse()->getSqlExecutor();
+ if ($this->_queryCacheProfile) {
+ $executor->setQueryCacheProfile($this->_queryCacheProfile);
+ }
// Prepare parameters
$paramMappings = $this->_parserResult->getParameterMappings();
@@ -523,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)
{
diff --git a/lib/Doctrine/ORM/Query/Exec/AbstractSqlExecutor.php b/lib/Doctrine/ORM/Query/Exec/AbstractSqlExecutor.php
index 7879b0ff2..f44e383b9 100644
--- a/lib/Doctrine/ORM/Query/Exec/AbstractSqlExecutor.php
+++ b/lib/Doctrine/ORM/Query/Exec/AbstractSqlExecutor.php
@@ -1,7 +1,5 @@
_sqlStatements;
}
+ public function setQueryCacheProfile(QueryCacheProfile $qcp)
+ {
+ $this->queryCacheProfile = $qcp;
+ }
+
/**
* Executes all sql statements.
*
* @param Doctrine\DBAL\Connection $conn The database connection that is used to execute the queries.
* @param array $params The parameters.
+ * @param array $types The parameter types.
* @return Doctrine\DBAL\Driver\Statement
*/
- abstract public function execute(Connection $conn, array $params, array $types);
+ abstract public function execute(Connection $conn, array $params, array $types);
}
\ No newline at end of file
diff --git a/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php b/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php
index a6c22cecd..5b07d4d02 100644
--- a/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php
+++ b/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php
@@ -1,7 +1,5 @@
- * @version $Revision$
* @link www.doctrine-project.org
* @since 2.0
*/
@@ -41,8 +38,11 @@ class SingleSelectExecutor extends AbstractSqlExecutor
$this->_sqlStatements = $sqlWalker->walkSelectStatement($AST);
}
+ /**
+ * {@inheritDoc}
+ */
public function execute(Connection $conn, array $params, array $types)
{
- return $conn->executeQuery($this->_sqlStatements, $params, $types);
+ return $conn->executeQuery($this->_sqlStatements, $params, $types, $this->queryCacheProfile);
}
}
diff --git a/lib/Doctrine/ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php b/lib/Doctrine/ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php
index 94db13b05..facccb715 100644
--- a/lib/Doctrine/ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php
+++ b/lib/Doctrine/ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php
@@ -1,7 +1,5 @@
- * @version $Revision$
* @link www.doctrine-project.org
* @since 2.0
* @todo This is exactly the same as SingleSelectExecutor. Unify in SingleStatementExecutor.
@@ -45,7 +42,10 @@ class SingleTableDeleteUpdateExecutor extends AbstractSqlExecutor
$this->_sqlStatements = $sqlWalker->walkDeleteStatement($AST);
}
}
-
+
+ /**
+ * {@inheritDoc}
+ */
public function execute(Connection $conn, array $params, array $types)
{
return $conn->executeUpdate($this->_sqlStatements, $params, $types);
diff --git a/lib/Doctrine/ORM/Query/Expr/Base.php b/lib/Doctrine/ORM/Query/Expr/Base.php
index beac2bb9c..975d450cd 100644
--- a/lib/Doctrine/ORM/Query/Expr/Base.php
+++ b/lib/Doctrine/ORM/Query/Expr/Base.php
@@ -57,7 +57,7 @@ abstract class Base
public function add($arg)
{
- if ( $arg !== null ) {
+ if ( $arg !== null || ($arg instanceof self && $arg->count() > 0) ) {
// If we decide to keep Expr\Base instances, we can use this check
if ( ! is_string($arg)) {
$class = get_class($arg);
diff --git a/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php b/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php
index d1690b72c..f84686ad2 100644
--- a/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php
+++ b/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php
@@ -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);
}
}
}
diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php
index 188350197..d90dc28f2 100644
--- a/lib/Doctrine/ORM/Query/SqlWalker.php
+++ b/lib/Doctrine/ORM/Query/SqlWalker.php
@@ -157,32 +157,24 @@ class SqlWalker implements TreeWalker
*/
public function getExecutor($AST)
{
- $isDeleteStatement = $AST instanceof AST\DeleteStatement;
- $isUpdateStatement = $AST instanceof AST\UpdateStatement;
+ switch (true) {
+ case ($AST instanceof AST\DeleteStatement):
+ $primaryClass = $this->_em->getClassMetadata($AST->deleteClause->abstractSchemaName);
- if ($isDeleteStatement) {
- $primaryClass = $this->_em->getClassMetadata(
- $AST->deleteClause->abstractSchemaName
- );
+ return ($primaryClass->isInheritanceTypeJoined())
+ ? new Exec\MultiTableDeleteExecutor($AST, $this)
+ : new Exec\SingleTableDeleteUpdateExecutor($AST, $this);
- if ($primaryClass->isInheritanceTypeJoined()) {
- return new Exec\MultiTableDeleteExecutor($AST, $this);
- } else {
- return new Exec\SingleTableDeleteUpdateExecutor($AST, $this);
- }
- } else if ($isUpdateStatement) {
- $primaryClass = $this->_em->getClassMetadata(
- $AST->updateClause->abstractSchemaName
- );
+ case ($AST instanceof AST\UpdateStatement):
+ $primaryClass = $this->_em->getClassMetadata($AST->updateClause->abstractSchemaName);
- if ($primaryClass->isInheritanceTypeJoined()) {
- return new Exec\MultiTableUpdateExecutor($AST, $this);
- } else {
- return new Exec\SingleTableDeleteUpdateExecutor($AST, $this);
- }
+ return ($primaryClass->isInheritanceTypeJoined())
+ ? new Exec\MultiTableUpdateExecutor($AST, $this)
+ : new Exec\SingleTableDeleteUpdateExecutor($AST, $this);
+
+ default:
+ return new Exec\SingleSelectExecutor($AST, $this);
}
-
- return new Exec\SingleSelectExecutor($AST, $this);
}
/**
@@ -229,7 +221,11 @@ class SqlWalker implements TreeWalker
*/
public function getSQLColumnAlias($columnName)
{
- return $columnName . $this->_aliasCounter++;
+ // 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->_aliasCounter++, -$this->_platform->getMaxIdentifierLength())
+ );
}
/**
@@ -250,16 +246,15 @@ class SqlWalker implements TreeWalker
foreach ($class->parentClasses as $parentClassName) {
$parentClass = $this->_em->getClassMetadata($parentClassName);
$tableAlias = $this->getSQLTableAlias($parentClass->getTableName(), $dqlAlias);
-
+
// If this is a joined association we must use left joins to preserve the correct result.
$sql .= isset($this->_queryComponents[$dqlAlias]['relation']) ? ' LEFT ' : ' INNER ';
$sql .= 'JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
$first = true;
-
- foreach ($class->identifier as $idField) {
+
+ foreach ($class->getQuotedIdentifierColumnNames($this->_platform) as $columnName) {
if ($first) $first = false; else $sql .= ' AND ';
- $columnName = $class->getQuotedColumnName($idField, $this->_platform);
$sql .= $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName;
}
}
@@ -271,11 +266,10 @@ class SqlWalker implements TreeWalker
$tableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias);
$sql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
$first = true;
-
- foreach ($class->identifier as $idField) {
+
+ foreach ($class->getQuotedIdentifierColumnNames($this->_platform) as $columnName) {
if ($first) $first = false; else $sql .= ' AND ';
- $columnName = $class->getQuotedColumnName($idField, $this->_platform);
$sql .= $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName;
}
}
@@ -287,10 +281,10 @@ class SqlWalker implements TreeWalker
private function _generateOrderedCollectionOrderByItems()
{
$sql = '';
-
+
foreach ($this->_selectedClasses AS $dqlAlias => $class) {
$qComp = $this->_queryComponents[$dqlAlias];
-
+
if (isset($qComp['relation']['orderBy'])) {
foreach ($qComp['relation']['orderBy'] AS $fieldName => $orientation) {
$tableName = ($qComp['metadata']->isInheritanceTypeJoined())
@@ -300,13 +294,13 @@ class SqlWalker implements TreeWalker
if ($sql != '') {
$sql .= ', ';
}
-
- $sql .= $this->getSQLTableAlias($tableName, $dqlAlias) . '.'
+
+ $sql .= $this->getSQLTableAlias($tableName, $dqlAlias) . '.'
. $qComp['metadata']->getQuotedColumnName($fieldName, $this->_platform) . ' ' . $orientation;
}
}
}
-
+
return $sql;
}
@@ -327,7 +321,7 @@ class SqlWalker implements TreeWalker
if ($class->isInheritanceTypeSingleTable()) {
$conn = $this->_em->getConnection();
$values = array();
-
+
if ($class->discriminatorValue !== null) { // discrimnators can be 0
$values[] = $conn->quote($class->discriminatorValue);
}
@@ -399,7 +393,7 @@ class SqlWalker implements TreeWalker
public function walkUpdateStatement(AST\UpdateStatement $AST)
{
$this->_useSqlTableAliases = false;
-
+
return $this->walkUpdateClause($AST->updateClause) . $this->walkWhereClause($AST->whereClause);
}
@@ -412,7 +406,7 @@ class SqlWalker implements TreeWalker
public function walkDeleteStatement(AST\DeleteStatement $AST)
{
$this->_useSqlTableAliases = false;
-
+
return $this->walkDeleteClause($AST->deleteClause) . $this->walkWhereClause($AST->whereClause);
}
@@ -477,7 +471,7 @@ class SqlWalker implements TreeWalker
if ( ! $assoc['isOwningSide']) {
throw QueryException::associationPathInverseSideNotSupported();
}
-
+
// COMPOSITE KEYS NOT (YET?) SUPPORTED
if (count($assoc['sourceToTargetKeyColumns']) > 1) {
throw QueryException::associationPathCompositeKeyNotSupported();
@@ -489,7 +483,7 @@ class SqlWalker implements TreeWalker
$sql .= reset($assoc['targetToSourceKeyColumns']);
break;
-
+
default:
throw QueryException::invalidPathExpression($pathExpr);
}
@@ -532,10 +526,9 @@ class SqlWalker implements TreeWalker
$tblAlias = $this->getSQLTableAlias($rootClass->getTableName(), $dqlAlias);
$discrColumn = $rootClass->discriminatorColumn;
$columnAlias = $this->getSQLColumnAlias($discrColumn['name']);
-
+
$sqlSelectExpressions[] = $tblAlias . '.' . $discrColumn['name'] . ' AS ' . $columnAlias;
- $columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
$this->_rsm->setDiscriminatorColumn($dqlAlias, $columnAlias);
$this->_rsm->addMetaResult($dqlAlias, $columnAlias, $discrColumn['fieldName']);
@@ -550,14 +543,13 @@ class SqlWalker implements TreeWalker
} else {
$sqlTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
}
-
+
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
$columnAlias = $this->getSQLColumnAlias($srcColumn);
-
+
$sqlSelectExpressions[] = $sqlTableAlias . '.' . $srcColumn . ' AS ' . $columnAlias;
-
- $columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
- $this->_rsm->addMetaResult($dqlAlias, $this->_platform->getSQLResultCasing($columnAlias), $srcColumn, (isset($assoc['id']) && $assoc['id'] === true));
+
+ $this->_rsm->addMetaResult($dqlAlias, $columnAlias, $srcColumn, (isset($assoc['id']) && $assoc['id'] === true));
}
}
}
@@ -566,23 +558,22 @@ class SqlWalker implements TreeWalker
// Add foreign key columns to SQL, if necessary
if ($addMetaColumns) {
$sqlTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
-
+
foreach ($class->associationMappings as $assoc) {
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
$columnAlias = $this->getSQLColumnAlias($srcColumn);
-
+
$sqlSelectExpressions[] = $sqlTableAlias . '.' . $srcColumn . ' AS ' . $columnAlias;
-
- $columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
- $this->_rsm->addMetaResult($dqlAlias, $this->_platform->getSQLResultCasing($columnAlias), $srcColumn, (isset($assoc['id']) && $assoc['id'] === true));
+
+ $this->_rsm->addMetaResult($dqlAlias, $columnAlias, $srcColumn, (isset($assoc['id']) && $assoc['id'] === true));
}
}
}
}
}
}
-
+
$sql .= implode(', ', $sqlSelectExpressions);
return $sql;
@@ -603,7 +594,7 @@ class SqlWalker implements TreeWalker
$rangeDecl = $identificationVariableDecl->rangeVariableDeclaration;
$dqlAlias = $rangeDecl->aliasIdentificationVariable;
-
+
$this->_rootAliases[] = $dqlAlias;
$class = $this->_em->getClassMetadata($rangeDecl->abstractSchemaName);
@@ -720,12 +711,12 @@ class SqlWalker implements TreeWalker
$joinAssocPathExpr = $join->joinAssociationPathExpression;
$joinedDqlAlias = $join->aliasIdentificationVariable;
-
+
$relation = $this->_queryComponents[$joinedDqlAlias]['relation'];
$targetClass = $this->_em->getClassMetadata($relation['targetEntity']);
$sourceClass = $this->_em->getClassMetadata($relation['sourceEntity']);
$targetTableName = $targetClass->getQuotedTableName($this->_platform);
-
+
$targetTableAlias = $this->getSQLTableAlias($targetClass->getTableName(), $joinedDqlAlias);
$sourceTableAlias = $this->getSQLTableAlias($sourceClass->getTableName(), $joinAssocPathExpr->identificationVariable);
@@ -860,7 +851,7 @@ class SqlWalker implements TreeWalker
return $sql;
}
-
+
/**
* Walks down a CaseExpression AST node and generates the corresponding SQL.
*
@@ -872,21 +863,21 @@ class SqlWalker implements TreeWalker
switch (true) {
case ($expression instanceof AST\CoalesceExpression):
return $this->walkCoalesceExpression($expression);
-
+
case ($expression instanceof AST\NullIfExpression):
return $this->walkNullIfExpression($expression);
-
+
case ($expression instanceof AST\GeneralCaseExpression):
return $this->walkGeneralCaseExpression($expression);
-
+
case ($expression instanceof AST\SimpleCaseExpression):
return $this->walkSimpleCaseExpression($expression);
-
+
default:
return '';
}
}
-
+
/**
* Walks down a CoalesceExpression AST node and generates the corresponding SQL.
*
@@ -896,18 +887,18 @@ class SqlWalker implements TreeWalker
public function walkCoalesceExpression($coalesceExpression)
{
$sql = 'COALESCE(';
-
+
$scalarExpressions = array();
-
+
foreach ($coalesceExpression->scalarExpressions as $scalarExpression) {
$scalarExpressions[] = $this->walkSimpleArithmeticExpression($scalarExpression);
}
-
+
$sql .= implode(', ', $scalarExpressions) . ')';
-
+
return $sql;
}
-
+
/**
* Walks down a NullIfExpression AST node and generates the corresponding SQL.
*
@@ -916,17 +907,17 @@ class SqlWalker implements TreeWalker
*/
public function walkNullIfExpression($nullIfExpression)
{
- $firstExpression = is_string($nullIfExpression->firstExpression)
+ $firstExpression = is_string($nullIfExpression->firstExpression)
? $this->_conn->quote($nullIfExpression->firstExpression)
: $this->walkSimpleArithmeticExpression($nullIfExpression->firstExpression);
-
- $secondExpression = is_string($nullIfExpression->secondExpression)
+
+ $secondExpression = is_string($nullIfExpression->secondExpression)
? $this->_conn->quote($nullIfExpression->secondExpression)
: $this->walkSimpleArithmeticExpression($nullIfExpression->secondExpression);
-
+
return 'NULLIF(' . $firstExpression . ', ' . $secondExpression . ')';
}
-
+
/**
* Walks down a GeneralCaseExpression AST node and generates the corresponding SQL.
*
@@ -936,17 +927,17 @@ class SqlWalker implements TreeWalker
public function walkGeneralCaseExpression(AST\GeneralCaseExpression $generalCaseExpression)
{
$sql = 'CASE';
-
+
foreach ($generalCaseExpression->whenClauses as $whenClause) {
$sql .= ' WHEN ' . $this->walkConditionalExpression($whenClause->caseConditionExpression);
$sql .= ' THEN ' . $this->walkSimpleArithmeticExpression($whenClause->thenScalarExpression);
}
-
+
$sql .= ' ELSE ' . $this->walkSimpleArithmeticExpression($generalCaseExpression->elseScalarExpression) . ' END';
-
+
return $sql;
}
-
+
/**
* Walks down a SimpleCaseExpression AST node and generates the corresponding SQL.
*
@@ -956,14 +947,14 @@ class SqlWalker implements TreeWalker
public function walkSimpleCaseExpression($simpleCaseExpression)
{
$sql = 'CASE ' . $this->walkStateFieldPathExpression($simpleCaseExpression->caseOperand);
-
+
foreach ($simpleCaseExpression->simpleWhenClauses as $simpleWhenClause) {
$sql .= ' WHEN ' . $this->walkSimpleArithmeticExpression($simpleWhenClause->caseScalarExpression);
$sql .= ' THEN ' . $this->walkSimpleArithmeticExpression($simpleWhenClause->thenScalarExpression);
}
-
+
$sql .= ' ELSE ' . $this->walkSimpleArithmeticExpression($simpleCaseExpression->elseScalarExpression) . ' END';
-
+
return $sql;
}
@@ -983,31 +974,26 @@ class SqlWalker implements TreeWalker
if ($expr->type !== AST\PathExpression::TYPE_STATE_FIELD) {
throw QueryException::invalidPathExpression($expr->type);
}
-
+
$fieldName = $expr->field;
$dqlAlias = $expr->identificationVariable;
$qComp = $this->_queryComponents[$dqlAlias];
$class = $qComp['metadata'];
- if ( ! $selectExpression->fieldIdentificationVariable) {
- $resultAlias = $fieldName;
- } else {
- $resultAlias = $selectExpression->fieldIdentificationVariable;
- }
+ $resultAlias = ( ! $selectExpression->fieldIdentificationVariable)
+ ? $fieldName
+ : $selectExpression->fieldIdentificationVariable;
- if ($class->isInheritanceTypeJoined()) {
- $tableName = $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName);
- } else {
- $tableName = $class->getTableName();
- }
+ $tableName = ($class->isInheritanceTypeJoined())
+ ? $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName)
+ : $class->getTableName();
$sqlTableAlias = $this->getSQLTableAlias($tableName, $dqlAlias);
$columnName = $class->getQuotedColumnName($fieldName, $this->_platform);
$columnAlias = $this->getSQLColumnAlias($columnName);
$sql .= $sqlTableAlias . '.' . $columnName . ' AS ' . $columnAlias;
- $columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
-
+
if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
}
@@ -1018,12 +1004,10 @@ class SqlWalker implements TreeWalker
$resultAlias = $selectExpression->fieldIdentificationVariable;
}
- $columnAlias = 'sclr' . $this->_aliasCounter++;
+ $columnAlias = $this->getSQLColumnAlias('sclr');
$sql .= $this->walkAggregateExpression($expr) . ' AS ' . $columnAlias;
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
- $columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
-
if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
}
@@ -1034,12 +1018,10 @@ class SqlWalker implements TreeWalker
$resultAlias = $selectExpression->fieldIdentificationVariable;
}
- $columnAlias = 'sclr' . $this->_aliasCounter++;
+ $columnAlias = $this->getSQLColumnAlias('sclr');
$sql .= '(' . $this->walkSubselect($expr) . ') AS '.$columnAlias;
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
- $columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
-
if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
}
@@ -1050,12 +1032,10 @@ class SqlWalker implements TreeWalker
$resultAlias = $selectExpression->fieldIdentificationVariable;
}
- $columnAlias = 'sclr' . $this->_aliasCounter++;
+ $columnAlias = $this->getSQLColumnAlias('sclr');
$sql .= $this->walkFunction($expr) . ' AS ' . $columnAlias;
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
- $columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
-
if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
}
@@ -1072,18 +1052,15 @@ class SqlWalker implements TreeWalker
$resultAlias = $selectExpression->fieldIdentificationVariable;
}
- $columnAlias = 'sclr' . $this->_aliasCounter++;
-
+ $columnAlias = $this->getSQLColumnAlias('sclr');
if ($expr instanceof AST\Literal) {
$sql .= $this->walkLiteral($expr) . ' AS ' .$columnAlias;
} else {
$sql .= $this->walkSimpleArithmeticExpression($expr) . ' AS ' . $columnAlias;
}
-
+
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
- $columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
-
if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
}
@@ -1099,14 +1076,11 @@ class SqlWalker implements TreeWalker
$resultAlias = $selectExpression->fieldIdentificationVariable;
}
- $columnAlias = 'sclr' . $this->_aliasCounter++;
-
+ $columnAlias = $this->getSQLColumnAlias('sclr');
$sql .= $this->walkCaseExpression($expr) . ' AS ' . $columnAlias;
-
+
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
- $columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
-
if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
}
@@ -1126,16 +1100,16 @@ class SqlWalker implements TreeWalker
if ( ! isset($this->_selectedClasses[$dqlAlias])) {
$this->_selectedClasses[$dqlAlias] = $class;
}
-
+
$beginning = true;
-
+
// Select all fields from the queried class
foreach ($class->fieldMappings as $fieldName => $mapping) {
if ($partialFieldSet && !in_array($fieldName, $partialFieldSet)) {
continue;
}
- $tableName = (isset($mapping['inherited']))
+ $tableName = (isset($mapping['inherited']))
? $this->_em->getClassMetadata($mapping['inherited'])->getTableName()
: $class->getTableName();
@@ -1146,8 +1120,6 @@ class SqlWalker implements TreeWalker
$sql .= $sqlTableAlias . '.' . $class->getQuotedColumnName($fieldName, $this->_platform)
. ' AS ' . $columnAlias;
- $columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
-
$this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $class->name);
}
@@ -1159,7 +1131,7 @@ class SqlWalker implements TreeWalker
foreach ($class->subClasses as $subClassName) {
$subClass = $this->_em->getClassMetadata($subClassName);
$sqlTableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias);
-
+
foreach ($subClass->fieldMappings as $fieldName => $mapping) {
if (isset($mapping['inherited']) || $partialFieldSet && !in_array($fieldName, $partialFieldSet)) {
continue;
@@ -1171,7 +1143,6 @@ class SqlWalker implements TreeWalker
$sql .= $sqlTableAlias . '.' . $subClass->getQuotedColumnName($fieldName, $this->_platform)
. ' AS ' . $columnAlias;
- $columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
$this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $subClassName);
}
@@ -1181,11 +1152,11 @@ class SqlWalker implements TreeWalker
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE && ! isset($assoc['inherited'])) {
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
if ($beginning) $beginning = false; else $sql .= ', ';
-
+
$columnAlias = $this->getSQLColumnAlias($srcColumn);
$sql .= $sqlTableAlias . '.' . $srcColumn . ' AS ' . $columnAlias;
-
- $this->_rsm->addMetaResult($dqlAlias, $this->_platform->getSQLResultCasing($columnAlias), $srcColumn);
+
+ $this->_rsm->addMetaResult($dqlAlias, $columnAlias, $srcColumn);
}
}
}
@@ -1292,83 +1263,77 @@ class SqlWalker implements TreeWalker
*/
public function walkSimpleSelectExpression($simpleSelectExpression)
{
- $sql = '';
$expr = $simpleSelectExpression->expression;
+ $sql = ' ';
- if ($expr instanceof AST\PathExpression) {
- $sql .= $this->walkPathExpression($expr);
- } else if ($expr instanceof AST\AggregateExpression) {
- if ( ! $simpleSelectExpression->fieldIdentificationVariable) {
- $alias = $this->_scalarResultCounter++;
- } else {
- $alias = $simpleSelectExpression->fieldIdentificationVariable;
- }
+ switch (true) {
+ case ($expr instanceof AST\PathExpression):
+ $sql .= $this->walkPathExpression($expr);
+ break;
- $sql .= $this->walkAggregateExpression($expr) . ' AS dctrn__' . $alias;
- } else if ($expr instanceof AST\Subselect) {
- if ( ! $simpleSelectExpression->fieldIdentificationVariable) {
- $alias = $this->_scalarResultCounter++;
- } else {
- $alias = $simpleSelectExpression->fieldIdentificationVariable;
- }
+ case ($expr instanceof AST\AggregateExpression):
+ $alias = $simpleSelectExpression->fieldIdentificationVariable ?: $this->_scalarResultCounter++;
- $columnAlias = 'sclr' . $this->_aliasCounter++;
- $sql .= '(' . $this->walkSubselect($expr) . ') AS ' . $columnAlias;
- $this->_scalarResultAliasMap[$alias] = $columnAlias;
- } else if ($expr instanceof AST\Functions\FunctionNode) {
- if ( ! $simpleSelectExpression->fieldIdentificationVariable) {
- $alias = $this->_scalarResultCounter++;
- } else {
- $alias = $simpleSelectExpression->fieldIdentificationVariable;
- }
+ $sql .= $this->walkAggregateExpression($expr) . ' AS dctrn__' . $alias;
+ break;
- $columnAlias = 'sclr' . $this->_aliasCounter++;
- $sql .= $this->walkFunction($expr) . ' AS ' . $columnAlias;
- $this->_scalarResultAliasMap[$alias] = $columnAlias;
- } else if (
- $expr instanceof AST\SimpleArithmeticExpression ||
- $expr instanceof AST\ArithmeticTerm ||
- $expr instanceof AST\ArithmeticFactor ||
- $expr instanceof AST\ArithmeticPrimary
- ) {
- if ( ! $simpleSelectExpression->fieldIdentificationVariable) {
- $alias = $this->_scalarResultCounter++;
- } else {
- $alias = $simpleSelectExpression->fieldIdentificationVariable;
- }
+ case ($expr instanceof AST\Subselect):
+ $alias = $simpleSelectExpression->fieldIdentificationVariable ?: $this->_scalarResultCounter++;
- $columnAlias = 'sclr' . $this->_aliasCounter++;
- $sql .= $this->walkSimpleArithmeticExpression($expr) . ' AS ' . $columnAlias;
- $this->_scalarResultAliasMap[$alias] = $columnAlias;
- } else if (
- $expr instanceof AST\NullIfExpression ||
- $expr instanceof AST\CoalesceExpression ||
- $expr instanceof AST\GeneralCaseExpression ||
- $expr instanceof AST\SimpleCaseExpression
- ) {
- if ( ! $simpleSelectExpression->fieldIdentificationVariable) {
- $alias = $this->_scalarResultCounter++;
- } else {
- $alias = $simpleSelectExpression->fieldIdentificationVariable;
- }
+ $columnAlias = 'sclr' . $this->_aliasCounter++;
+ $this->_scalarResultAliasMap[$alias] = $columnAlias;
- $columnAlias = 'sclr' . $this->_aliasCounter++;
- $sql .= $this->walkCaseExpression($expr) . ' AS ' . $columnAlias;
-
- $this->_scalarResultAliasMap[$alias] = $columnAlias;
- } else {
- // IdentificationVariable
- $class = $this->_queryComponents[$expr]['metadata'];
- $tableAlias = $this->getSQLTableAlias($class->getTableName(), $expr);
- $first = true;
+ $sql .= '(' . $this->walkSubselect($expr) . ') AS ' . $columnAlias;
+ break;
- foreach ($class->identifier as $identifier) {
- if ($first) $first = false; else $sql .= ', ';
- $sql .= $tableAlias . '.' . $class->getQuotedColumnName($identifier, $this->_platform);
- }
+ case ($expr instanceof AST\Functions\FunctionNode):
+ $alias = $simpleSelectExpression->fieldIdentificationVariable ?: $this->_scalarResultCounter++;
+
+ $columnAlias = $this->getSQLColumnAlias('sclr');
+ $this->_scalarResultAliasMap[$alias] = $columnAlias;
+
+ $sql .= $this->walkFunction($expr) . ' AS ' . $columnAlias;
+ break;
+
+ case ($expr instanceof AST\SimpleArithmeticExpression):
+ case ($expr instanceof AST\ArithmeticTerm):
+ case ($expr instanceof AST\ArithmeticFactor):
+ case ($expr instanceof AST\ArithmeticPrimary):
+ case ($expr instanceof AST\Literal):
+ $alias = $simpleSelectExpression->fieldIdentificationVariable ?: $this->_scalarResultCounter++;
+
+ $columnAlias = $this->getSQLColumnAlias('sclr');
+ $this->_scalarResultAliasMap[$alias] = $columnAlias;
+
+ $sql .= $this->walkSimpleArithmeticExpression($expr) . ' AS ' . $columnAlias;
+ break;
+
+ case ($expr instanceof AST\NullIfExpression):
+ case ($expr instanceof AST\CoalesceExpression):
+ case ($expr instanceof AST\GeneralCaseExpression):
+ case ($expr instanceof AST\SimpleCaseExpression):
+ $alias = $simpleSelectExpression->fieldIdentificationVariable ?: $this->_scalarResultCounter++;
+
+ $columnAlias = $this->getSQLColumnAlias('sclr');
+ $this->_scalarResultAliasMap[$alias] = $columnAlias;
+
+ $sql .= $this->walkCaseExpression($expr) . ' AS ' . $columnAlias;
+ break;
+
+ default: // IdentificationVariable
+ $class = $this->_queryComponents[$expr]['metadata'];
+ $tableAlias = $this->getSQLTableAlias($class->getTableName(), $expr);
+ $sqlParts = array();
+
+ foreach ($class->getQuotedIdentifierColumnNames($this->_platform) as $columnName) {
+ $sqlParts[] = $tableAlias . '.' . $columnName;
+ }
+
+ $sql .= implode(', ', $sqlParts);
+ break;
}
- return ' ' . $sql;
+ return $sql;
}
/**
@@ -1391,25 +1356,24 @@ class SqlWalker implements TreeWalker
*/
public function walkGroupByClause($groupByClause)
{
- $sql = '';
+ $sqlParts = array();
+
foreach ($groupByClause->groupByItems AS $groupByItem) {
- if (is_string($groupByItem)) {
- foreach ($this->_queryComponents[$groupByItem]['metadata']->identifier AS $idField) {
- if ($sql != '') {
- $sql .= ', ';
- }
- $groupByItem = new AST\PathExpression(AST\PathExpression::TYPE_STATE_FIELD, $groupByItem, $idField);
- $groupByItem->type = AST\PathExpression::TYPE_STATE_FIELD;
- $sql .= $this->walkGroupByItem($groupByItem);
- }
- } else {
- if ($sql != '') {
- $sql .= ', ';
- }
- $sql .= $this->walkGroupByItem($groupByItem);
+ if ( ! is_string($groupByItem)) {
+ $sqlParts[] = $this->walkGroupByItem($groupByItem);
+
+ continue;
+ }
+
+ foreach ($this->_queryComponents[$groupByItem]['metadata']->identifier AS $idField) {
+ $groupByItem = new AST\PathExpression(AST\PathExpression::TYPE_STATE_FIELD, $groupByItem, $idField);
+ $groupByItem->type = AST\PathExpression::TYPE_STATE_FIELD;
+
+ $sqlParts[] = $this->walkGroupByItem($groupByItem);
}
}
- return ' GROUP BY ' . $sql;
+
+ return ' GROUP BY ' . implode(', ', $sqlParts);
}
/**
@@ -1431,12 +1395,11 @@ class SqlWalker implements TreeWalker
*/
public function walkDeleteClause(AST\DeleteClause $deleteClause)
{
- $sql = 'DELETE FROM ';
- $class = $this->_em->getClassMetadata($deleteClause->abstractSchemaName);
- $sql .= $class->getQuotedTableName($this->_platform);
-
- $this->setSQLTableAlias($class->getTableName(), $class->getTableName(), $deleteClause->aliasIdentificationVariable);
+ $class = $this->_em->getClassMetadata($deleteClause->abstractSchemaName);
+ $tableName = $class->getTableName();
+ $sql = 'DELETE FROM ' . $class->getQuotedTableName($this->_platform);
+ $this->setSQLTableAlias($tableName, $tableName, $deleteClause->aliasIdentificationVariable);
$this->_rootAliases[] = $deleteClause->aliasIdentificationVariable;
return $sql;
@@ -1450,17 +1413,14 @@ class SqlWalker implements TreeWalker
*/
public function walkUpdateClause($updateClause)
{
- $sql = 'UPDATE ';
- $class = $this->_em->getClassMetadata($updateClause->abstractSchemaName);
- $sql .= $class->getQuotedTableName($this->_platform);
-
- $this->setSQLTableAlias($class->getTableName(), $class->getTableName(), $updateClause->aliasIdentificationVariable);
+ $class = $this->_em->getClassMetadata($updateClause->abstractSchemaName);
+ $tableName = $class->getTableName();
+ $sql = 'UPDATE ' . $class->getQuotedTableName($this->_platform);
+ $this->setSQLTableAlias($tableName, $tableName, $updateClause->aliasIdentificationVariable);
$this->_rootAliases[] = $updateClause->aliasIdentificationVariable;
- $sql .= ' SET ' . implode(
- ', ', array_map(array($this, 'walkUpdateItem'), $updateClause->updateItems)
- );
+ $sql .= ' SET ' . implode(', ', array_map(array($this, 'walkUpdateItem'), $updateClause->updateItems));
return $sql;
}
@@ -1476,16 +1436,21 @@ class SqlWalker implements TreeWalker
$useTableAliasesBefore = $this->_useSqlTableAliases;
$this->_useSqlTableAliases = false;
- $sql = $this->walkPathExpression($updateItem->pathExpression) . ' = ';
-
+ $sql = $this->walkPathExpression($updateItem->pathExpression) . ' = ';
$newValue = $updateItem->newValue;
- if ($newValue === null) {
- $sql .= 'NULL';
- } else if ($newValue instanceof AST\Node) {
- $sql .= $newValue->dispatch($this);
- } else {
- $sql .= $this->_conn->quote($newValue);
+ switch (true) {
+ case ($newValue instanceof AST\Node):
+ $sql .= $newValue->dispatch($this);
+ break;
+
+ case ($newValue === null):
+ $sql .= 'NULL';
+ break;
+
+ default:
+ $sql .= $this->_conn->quote($newValue);
+ break;
}
$this->_useSqlTableAliases = $useTableAliasesBefore;
@@ -1502,12 +1467,14 @@ class SqlWalker implements TreeWalker
*/
public function walkWhereClause($whereClause)
{
- $condSql = null !== $whereClause ? $this->walkConditionalExpression($whereClause->conditionalExpression) : '';
+ $condSql = null !== $whereClause ? $this->walkConditionalExpression($whereClause->conditionalExpression) : '';
$discrSql = $this->_generateDiscriminatorColumnConditionSql($this->_rootAliases);
if ($condSql) {
return ' WHERE ' . (( ! $discrSql) ? $condSql : '(' . $condSql . ') AND ' . $discrSql);
- } else if ($discrSql) {
+ }
+
+ if ($discrSql) {
return ' WHERE ' . $discrSql;
}
@@ -1524,11 +1491,11 @@ class SqlWalker implements TreeWalker
{
// Phase 2 AST optimization: Skip processment of ConditionalExpression
// if only one ConditionalTerm is defined
- return ( ! ($condExpr instanceof AST\ConditionalExpression))
- ? $this->walkConditionalTerm($condExpr)
- : implode(
- ' OR ', array_map(array($this, 'walkConditionalTerm'), $condExpr->conditionalTerms)
- );
+ if ( ! ($condExpr instanceof AST\ConditionalExpression)) {
+ return $this->walkConditionalTerm($condExpr);
+ }
+
+ return implode(' OR ', array_map(array($this, 'walkConditionalTerm'), $condExpr->conditionalTerms));
}
/**
@@ -1541,11 +1508,11 @@ class SqlWalker implements TreeWalker
{
// Phase 2 AST optimization: Skip processment of ConditionalTerm
// if only one ConditionalFactor is defined
- return ( ! ($condTerm instanceof AST\ConditionalTerm))
- ? $this->walkConditionalFactor($condTerm)
- : implode(
- ' AND ', array_map(array($this, 'walkConditionalFactor'), $condTerm->conditionalFactors)
- );
+ if ( ! ($condTerm instanceof AST\ConditionalTerm)) {
+ return $this->walkConditionalFactor($condTerm);
+ }
+
+ return implode(' AND ', array_map(array($this, 'walkConditionalFactor'), $condTerm->conditionalFactors));
}
/**
@@ -1573,7 +1540,9 @@ class SqlWalker implements TreeWalker
{
if ($primary->isSimpleConditionalExpression()) {
return $primary->simpleConditionalExpression->dispatch($this);
- } else if ($primary->isConditionalExpression()) {
+ }
+
+ if ($primary->isConditionalExpression()) {
$condExpr = $primary->conditionalExpression;
return '(' . $this->walkConditionalExpression($condExpr) . ')';
@@ -1607,12 +1576,12 @@ class SqlWalker implements TreeWalker
$sql .= 'EXISTS (SELECT 1 FROM ';
$entityExpr = $collMemberExpr->entityExpression;
$collPathExpr = $collMemberExpr->collectionValuedPathExpression;
-
+
$fieldName = $collPathExpr->field;
$dqlAlias = $collPathExpr->identificationVariable;
-
+
$class = $this->_queryComponents[$dqlAlias]['metadata'];
-
+
if ($entityExpr instanceof AST\InputParameter) {
$dqlParamKey = $entityExpr->name;
$entity = $this->_query->getParameter($dqlParamKey);
@@ -1620,40 +1589,39 @@ class SqlWalker implements TreeWalker
//TODO
throw new \BadMethodCallException("Not implemented");
}
-
+
$assoc = $class->associationMappings[$fieldName];
-
+
if ($assoc['type'] == ClassMetadata::ONE_TO_MANY) {
$targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
$targetTableAlias = $this->getSQLTableAlias($targetClass->getTableName());
$sourceTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
-
+
$sql .= $targetClass->getQuotedTableName($this->_platform) . ' ' . $targetTableAlias . ' WHERE ';
-
+
$owningAssoc = $targetClass->associationMappings[$assoc['mappedBy']];
$first = true;
-
+
foreach ($owningAssoc['targetToSourceKeyColumns'] as $targetColumn => $sourceColumn) {
if ($first) $first = false; else $sql .= ' AND ';
-
- $sql .= $sourceTableAlias . '.' . $class->getQuotedColumnName($class->fieldNames[$targetColumn], $this->_platform)
- . ' = '
+
+ $sql .= $sourceTableAlias . '.' . $class->getQuotedColumnName($class->fieldNames[$targetColumn], $this->_platform)
+ . ' = '
. $targetTableAlias . '.' . $sourceColumn;
}
-
+
$sql .= ' AND ';
$first = true;
-
- foreach ($targetClass->identifier as $idField) {
+
+ foreach ($targetClass->getQuotedIdentifierColumnNames($this->_platform) as $targetColumnName) {
if ($first) $first = false; else $sql .= ' AND ';
-
+
$this->_parserResult->addParameterMapping($dqlParamKey, $this->_sqlParamIndex++);
- $sql .= $targetTableAlias . '.'
- . $targetClass->getQuotedColumnName($idField, $this->_platform) . ' = ?';
+ $sql .= $targetTableAlias . '.' . $targetColumnName . ' = ?';
}
} else { // many-to-many
$targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
-
+
$owningAssoc = $assoc['isOwningSide'] ? $assoc : $targetClass->associationMappings[$assoc['mappedBy']];
$joinTable = $owningAssoc['joinTable'];
@@ -1661,11 +1629,11 @@ class SqlWalker implements TreeWalker
$joinTableAlias = $this->getSQLTableAlias($joinTable['name']);
$targetTableAlias = $this->getSQLTableAlias($targetClass->getTableName());
$sourceTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
-
+
// join to target table
- $sql .= $targetClass->getQuotedJoinTableName($owningAssoc, $this->_platform) . ' ' . $joinTableAlias
+ $sql .= $targetClass->getQuotedJoinTableName($owningAssoc, $this->_platform) . ' ' . $joinTableAlias
. ' INNER JOIN ' . $targetClass->getQuotedTableName($this->_platform) . ' ' . $targetTableAlias . ' ON ';
-
+
// join conditions
$joinColumns = $assoc['isOwningSide']
? $joinTable['inverseJoinColumns']
@@ -1683,29 +1651,28 @@ class SqlWalker implements TreeWalker
$joinColumns = $assoc['isOwningSide'] ? $joinTable['joinColumns'] : $joinTable['inverseJoinColumns'];
$first = true;
-
+
foreach ($joinColumns as $joinColumn) {
if ($first) $first = false; else $sql .= ' AND ';
- $sql .= $joinTableAlias . '.' . $joinColumn['name'] . ' = '
+ $sql .= $joinTableAlias . '.' . $joinColumn['name'] . ' = '
. $sourceTableAlias . '.' . $class->getQuotedColumnName($class->fieldNames[$joinColumn['referencedColumnName']], $this->_platform);
}
-
+
$sql .= ' AND ';
$first = true;
-
- foreach ($targetClass->identifier as $idField) {
+
+ foreach ($targetClass->getQuotedIdentifierColumnNames($this->_platform) as $targetColumnName) {
if ($first) $first = false; else $sql .= ' AND ';
-
+
$this->_parserResult->addParameterMapping($dqlParamKey, $this->_sqlParamIndex++);
- $sql .= $targetTableAlias . '.'
- . $targetClass->getQuotedColumnName($idField, $this->_platform) . ' = ?';
+ $sql .= $targetTableAlias . '.' . $targetColumnName . ' = ?';
}
}
return $sql . ')';
}
-
+
/**
* Walks down an EmptyCollectionComparisonExpression AST node, thereby generating the appropriate SQL.
*
@@ -1755,11 +1722,9 @@ class SqlWalker implements TreeWalker
$sql = $this->walkPathExpression($inExpr->pathExpression)
. ($inExpr->not ? ' NOT' : '') . ' IN (';
- if ($inExpr->subselect) {
- $sql .= $this->walkSubselect($inExpr->subselect);
- } else {
- $sql .= implode(', ', array_map(array($this, 'walkInParameter'), $inExpr->literals));
- }
+ $sql .= ($inExpr->subselect)
+ ? $this->walkSubselect($inExpr->subselect)
+ : implode(', ', array_map(array($this, 'walkInParameter'), $inExpr->literals));
$sql .= ')';
@@ -1787,11 +1752,11 @@ class SqlWalker implements TreeWalker
if ($this->_useSqlTableAliases) {
$sql .= $this->getSQLTableAlias($discrClass->getTableName(), $dqlAlias) . '.';
}
-
+
$sql .= $class->discriminatorColumn['name'] . ($instanceOfExpr->not ? ' NOT IN ' : ' IN ');
-
+
$sqlParameterList = array();
-
+
foreach ($instanceOfExpr->value as $parameter) {
if ($parameter instanceof AST\InputParameter) {
// We need to modify the parameter value to be its correspondent mapped value
@@ -1812,7 +1777,7 @@ class SqlWalker implements TreeWalker
$sqlParameterList[] = $this->_conn->quote($class->discriminatorValue);
} else {
$discrMap = array_flip($class->discriminatorMap);
-
+
if (!isset($discrMap[$entityClassName])) {
throw QueryException::instanceOfUnrelatedClass($entityClassName, $class->rootEntityName);
}
@@ -1820,7 +1785,7 @@ class SqlWalker implements TreeWalker
$sqlParameterList[] = $this->_conn->quote($discrMap[$entityClassName]);
}
}
-
+
$sql .= '(' . implode(', ', $sqlParameterList) . ')';
return $sql;
@@ -1834,9 +1799,9 @@ class SqlWalker implements TreeWalker
*/
public function walkInParameter($inParam)
{
- return $inParam instanceof AST\InputParameter ?
- $this->walkInputParameter($inParam) :
- $this->walkLiteral($inParam);
+ return $inParam instanceof AST\InputParameter
+ ? $this->walkInputParameter($inParam)
+ : $this->walkLiteral($inParam);
}
/**
@@ -1850,16 +1815,16 @@ class SqlWalker implements TreeWalker
switch ($literal->type) {
case AST\Literal::STRING:
return $this->_conn->quote($literal->value);
-
+
case AST\Literal::BOOLEAN:
$bool = strtolower($literal->value) == 'true' ? true : false;
$boolVal = $this->_conn->getDatabasePlatform()->convertBooleans($bool);
-
+
return $boolVal;
-
+
case AST\Literal::NUMERIC:
return $literal->value;
-
+
default:
throw QueryException::invalidLiteral($literal);
}
@@ -1929,23 +1894,19 @@ class SqlWalker implements TreeWalker
*/
public function walkComparisonExpression($compExpr)
{
- $sql = '';
- $leftExpr = $compExpr->leftExpression;
+ $leftExpr = $compExpr->leftExpression;
$rightExpr = $compExpr->rightExpression;
+ $sql = '';
- if ($leftExpr instanceof AST\Node) {
- $sql .= $leftExpr->dispatch($this);
- } else {
- $sql .= is_numeric($leftExpr) ? $leftExpr : $this->_conn->quote($leftExpr);
- }
+ $sql .= ($leftExpr instanceof AST\Node)
+ ? $leftExpr->dispatch($this)
+ : (is_numeric($leftExpr) ? $leftExpr : $this->_conn->quote($leftExpr));
$sql .= ' ' . $compExpr->operator . ' ';
- if ($rightExpr instanceof AST\Node) {
- $sql .= $rightExpr->dispatch($this);
- } else {
- $sql .= is_numeric($rightExpr) ? $rightExpr : $this->_conn->quote($rightExpr);
- }
+ $sql .= ($rightExpr instanceof AST\Node)
+ ? $rightExpr->dispatch($this)
+ : (is_numeric($rightExpr) ? $rightExpr : $this->_conn->quote($rightExpr));
return $sql;
}
@@ -1984,11 +1945,11 @@ class SqlWalker implements TreeWalker
*/
public function walkSimpleArithmeticExpression($simpleArithmeticExpr)
{
- return ( ! ($simpleArithmeticExpr instanceof AST\SimpleArithmeticExpression))
- ? $this->walkArithmeticTerm($simpleArithmeticExpr)
- : implode(
- ' ', array_map(array($this, 'walkArithmeticTerm'), $simpleArithmeticExpr->arithmeticTerms)
- );
+ if ( ! ($simpleArithmeticExpr instanceof AST\SimpleArithmeticExpression)) {
+ return $this->walkArithmeticTerm($simpleArithmeticExpr);
+ }
+
+ return implode(' ', array_map(array($this, 'walkArithmeticTerm'), $simpleArithmeticExpr->arithmeticTerms));
}
/**
@@ -2000,22 +1961,18 @@ class SqlWalker implements TreeWalker
public function walkArithmeticTerm($term)
{
if (is_string($term)) {
- if (isset($this->_queryComponents[$term])) {
- $columnName = $this->_queryComponents[$term]['token']['value'];
-
- return $this->_scalarResultAliasMap[$columnName];
- }
-
- return $term;
+ return (isset($this->_queryComponents[$term]))
+ ? $this->_scalarResultAliasMap[$this->_queryComponents[$term]['token']['value']]
+ : $term;
}
// Phase 2 AST optimization: Skip processment of ArithmeticTerm
// if only one ArithmeticFactor is defined
- return ( ! ($term instanceof AST\ArithmeticTerm))
- ? $this->walkArithmeticFactor($term)
- : implode(
- ' ', array_map(array($this, 'walkArithmeticFactor'), $term->arithmeticFactors)
- );
+ if ( ! ($term instanceof AST\ArithmeticTerm)) {
+ return $this->walkArithmeticFactor($term);
+ }
+
+ return implode(' ', array_map(array($this, 'walkArithmeticFactor'), $term->arithmeticFactors));
}
/**
@@ -2029,13 +1986,16 @@ class SqlWalker implements TreeWalker
if (is_string($factor)) {
return $factor;
}
-
+
// Phase 2 AST optimization: Skip processment of ArithmeticFactor
// if only one ArithmeticPrimary is defined
- return ( ! ($factor instanceof AST\ArithmeticFactor))
- ? $this->walkArithmeticPrimary($factor)
- : ($factor->isNegativeSigned() ? '-' : ($factor->isPositiveSigned() ? '+' : ''))
- . $this->walkArithmeticPrimary($factor->arithmeticPrimary);
+ if ( ! ($factor instanceof AST\ArithmeticFactor)) {
+ return $this->walkArithmeticPrimary($factor);
+ }
+
+ $sign = $factor->isNegativeSigned() ? '-' : ($factor->isPositiveSigned() ? '+' : '');
+
+ return $sign . $this->walkArithmeticPrimary($factor->arithmeticPrimary);
}
/**
@@ -2048,7 +2008,9 @@ class SqlWalker implements TreeWalker
{
if ($primary instanceof AST\SimpleArithmeticExpression) {
return '(' . $this->walkSimpleArithmeticExpression($primary) . ')';
- } else if ($primary instanceof AST\Node) {
+ }
+
+ if ($primary instanceof AST\Node) {
return $primary->dispatch($this);
}
diff --git a/lib/Doctrine/ORM/Tools/SchemaTool.php b/lib/Doctrine/ORM/Tools/SchemaTool.php
index 77106ec7d..568a960a4 100644
--- a/lib/Doctrine/ORM/Tools/SchemaTool.php
+++ b/lib/Doctrine/ORM/Tools/SchemaTool.php
@@ -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
@@ -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.
diff --git a/lib/Doctrine/ORM/Tools/SchemaValidator.php b/lib/Doctrine/ORM/Tools/SchemaValidator.php
index a7f8e3a1c..2ddd0bf66 100644
--- a/lib/Doctrine/ORM/Tools/SchemaValidator.php
+++ b/lib/Doctrine/ORM/Tools/SchemaValidator.php
@@ -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,165 @@ 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(), $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(), $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'])) {
+ $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(), $assoc['joinColumns'])) .
+ "' 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.
*
diff --git a/lib/Doctrine/ORM/Tools/ToolsException.php b/lib/Doctrine/ORM/Tools/ToolsException.php
index f7ed87105..4551d87da 100644
--- a/lib/Doctrine/ORM/Tools/ToolsException.php
+++ b/lib/Doctrine/ORM/Tools/ToolsException.php
@@ -1,11 +1,38 @@
.
+ */
namespace Doctrine\ORM\Tools;
use Doctrine\ORM\ORMException;
+/**
+ * Tools related Exceptions
+ *
+ * @author Benjamin Eberlei
+ */
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'!");
diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php
index 4366250dd..6add3bd6b 100644
--- a/lib/Doctrine/ORM/UnitOfWork.php
+++ b/lib/Doctrine/ORM/UnitOfWork.php
@@ -471,19 +471,21 @@ class UnitOfWork implements PropertyChangedListener
*/
public function computeChangeSet(ClassMetadata $class, $entity)
{
- if ( ! $class->isInheritanceTypeNone()) {
- $class = $this->em->getClassMetadata(get_class($entity));
- }
-
$oid = spl_object_hash($entity);
if (isset($this->readOnlyObjects[$oid])) {
return;
}
+ if ( ! $class->isInheritanceTypeNone()) {
+ $class = $this->em->getClassMetadata(get_class($entity));
+ }
+
$actualData = array();
+
foreach ($class->reflFields as $name => $refProp) {
$value = $refProp->getValue($entity);
+
if (isset($class->associationMappings[$name])
&& ($class->associationMappings[$name]['type'] & ClassMetadata::TO_MANY)
&& $value !== null
@@ -2054,6 +2056,11 @@ class UnitOfWork implements PropertyChangedListener
// Loading the entity right here, if its in the eager loading map get rid of it there.
unset($this->eagerLoadingEntities[$class->rootEntityName][$idHash]);
+ if (isset($this->eagerLoadingEntities[$class->rootEntityName]) &&
+ ! $this->eagerLoadingEntities[$class->rootEntityName]) {
+ unset($this->eagerLoadingEntities[$class->rootEntityName]);
+ }
+
// Properly initialize any unfetched associations, if partial objects are not allowed.
if ( ! isset($hints[Query::HINT_FORCE_PARTIAL_LOAD])) {
foreach ($class->associationMappings as $field => $assoc) {
diff --git a/tests/Doctrine/Tests/Models/DDC117/DDC117Article.php b/tests/Doctrine/Tests/Models/DDC117/DDC117Article.php
index 51ea2278d..70b1c6353 100644
--- a/tests/Doctrine/Tests/Models/DDC117/DDC117Article.php
+++ b/tests/Doctrine/Tests/Models/DDC117/DDC117Article.php
@@ -9,6 +9,7 @@ class DDC117Article
{
/** @Id @Column(type="integer", name="article_id") @GeneratedValue */
private $id;
+
/** @Column */
private $title;
diff --git a/tests/Doctrine/Tests/Models/Legacy/LegacyUser.php b/tests/Doctrine/Tests/Models/Legacy/LegacyUser.php
index f4f5e1fcb..3e3deedb1 100644
--- a/tests/Doctrine/Tests/Models/Legacy/LegacyUser.php
+++ b/tests/Doctrine/Tests/Models/Legacy/LegacyUser.php
@@ -21,7 +21,7 @@ class LegacyUser
*/
public $_username;
/**
- * @Column(type="string", length=255)
+ * @Column(type="string", length=255, name="name")
*/
public $_name;
/**
diff --git a/tests/Doctrine/Tests/Models/Legacy/LegacyUserReference.php b/tests/Doctrine/Tests/Models/Legacy/LegacyUserReference.php
index c6cd891a1..e666ae196 100644
--- a/tests/Doctrine/Tests/Models/Legacy/LegacyUserReference.php
+++ b/tests/Doctrine/Tests/Models/Legacy/LegacyUserReference.php
@@ -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;
diff --git a/tests/Doctrine/Tests/ORM/Functional/CustomTreeWalkersTest.php b/tests/Doctrine/Tests/ORM/Functional/CustomTreeWalkersTest.php
index ada41d00b..72fc6d587 100644
--- a/tests/Doctrine/Tests/ORM/Functional/CustomTreeWalkersTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/CustomTreeWalkersTest.php
@@ -1,7 +1,5 @@
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 "
-
+
$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
diff --git a/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php b/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php
index 4f8e11420..719a9f993 100644
--- a/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php
@@ -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");
}
-
+
}
diff --git a/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php b/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
index 4bf010602..351c1e25b 100644
--- a/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
@@ -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();
diff --git a/tests/Doctrine/Tests/ORM/Functional/NativeQueryTest.php b/tests/Doctrine/Tests/ORM/Functional/NativeQueryTest.php
index 3c41e0201..eb46329f1 100644
--- a/tests/Doctrine/Tests/ORM/Functional/NativeQueryTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/NativeQueryTest.php
@@ -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);
diff --git a/tests/Doctrine/Tests/ORM/Functional/ReadOnlyTest.php b/tests/Doctrine/Tests/ORM/Functional/ReadOnlyTest.php
index 8a5819956..44832fc76 100644
--- a/tests/Doctrine/Tests/ORM/Functional/ReadOnlyTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/ReadOnlyTest.php
@@ -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;
}
}
\ No newline at end of file
diff --git a/tests/Doctrine/Tests/ORM/Functional/ResultCacheTest.php b/tests/Doctrine/Tests/ORM/Functional/ResultCacheTest.php
index 235b4c91c..3dcae4fab 100644
--- a/tests/Doctrine/Tests/ORM/Functional/ResultCacheTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/ResultCacheTest.php
@@ -90,10 +90,10 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testUseResultCache()
{
$cache = new \Doctrine\Common\Cache\ArrayCache();
- $this->_em->getConfiguration()->setResultCacheImpl($cache);
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
$query->useResultCache(true);
+ $query->setResultCacheDriver($cache);
$query->setResultCacheId('testing_result_cache_id');
$users = $query->getResult();
@@ -108,11 +108,11 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testUseResultCacheParams()
{
$cache = new \Doctrine\Common\Cache\ArrayCache();
- $this->_em->getConfiguration()->setResultCacheImpl($cache);
$sqlCount = count($this->_sqlLoggerStack->queries);
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux WHERE ux.id = ?1');
$query->setParameter(1, 1);
+ $query->setResultCacheDriver($cache);
$query->useResultCache(true);
$query->getResult();
@@ -149,10 +149,10 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
}
/**
- * @param $query
+ * @param string $query
* @depends testNativeQueryResultCaching
*/
- public function testResultCacheDependsOnQueryHints($query)
+ public function testResultCacheNotDependsOnQueryHints($query)
{
$cache = $query->getResultCacheDriver();
$cacheCount = $this->getCacheSize($cache);
@@ -160,7 +160,7 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
$query->setHint('foo', 'bar');
$query->getResult();
- $this->assertEquals($cacheCount + 1, $this->getCacheSize($cache));
+ $this->assertEquals($cacheCount, $this->getCacheSize($cache));
}
/**
@@ -182,7 +182,7 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
* @param $query
* @depends testNativeQueryResultCaching
*/
- public function testResultCacheDependsOnHydrationMode($query)
+ public function testResultCacheNotDependsOnHydrationMode($query)
{
$cache = $query->getResultCacheDriver();
$cacheCount = $this->getCacheSize($cache);
@@ -190,7 +190,7 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertNotEquals(\Doctrine\ORM\Query::HYDRATE_ARRAY, $query->getHydrationMode());
$query->getArrayResult();
- $this->assertEquals($cacheCount + 1, $this->getCacheSize($cache));
+ $this->assertEquals($cacheCount, $this->getCacheSize($cache));
}
/**
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1040Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1040Test.php
index 21a042187..93dc0eea6 100644
--- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1040Test.php
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1040Test.php
@@ -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);
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1209Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1209Test.php
index 472978bc2..bddbbdf44 100644
--- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1209Test.php
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1209Test.php
@@ -106,7 +106,7 @@ class DDC1209_3
{
/**
* @Id
- * @Column(type="datetime")
+ * @Column(type="datetime", name="somedate")
*/
private $date;
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1225Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1225Test.php
index cec258f37..95dcc2b65 100644
--- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1225Test.php
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1225Test.php
@@ -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())
);
}
}
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1228Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1228Test.php
index 34aef78cf..6e14e2111 100644
--- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1228Test.php
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1228Test.php
@@ -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;
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1238Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1238Test.php
index 467577a43..6783928ef 100644
--- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1238Test.php
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1238Test.php
@@ -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;
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1335Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1335Test.php
index e12ee9ab7..e283b9f1c 100644
--- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1335Test.php
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1335Test.php
@@ -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;
}
}
\ No newline at end of file
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1454Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1454Test.php
new file mode 100644
index 000000000..eaf9dd3f9
--- /dev/null
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1454Test.php
@@ -0,0 +1,69 @@
+_schemaTool->createSchema(array(
+ $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1454File'),
+ $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1454Picture'),
+ ));
+ } catch (\Exception $ignored) {
+
+ }
+ }
+
+ public function testFailingCase()
+ {
+ $pic = new DDC1454Picture();
+ $this->_em->getUnitOfWork()->getEntityState($pic);
+ }
+
+}
+
+/**
+ * @Entity
+ */
+class DDC1454Picture extends DDC1454File
+{
+
+}
+
+/**
+ * @Entity
+ * @InheritanceType("JOINED")
+ * @DiscriminatorColumn(name="discr", type="string")
+ * @DiscriminatorMap({"picture" = "DDC1454Picture"})
+ */
+class DDC1454File
+{
+ /**
+ * @Column(name="file_id", type="integer")
+ * @Id
+ */
+ public $fileId;
+
+ public function __construct() {
+ $this->fileId = rand();
+ }
+
+ /**
+ * Get fileId
+ */
+ public function getFileId() {
+ return $this->fileId;
+ }
+
+}
\ No newline at end of file
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC331Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC331Test.php
index 512b1c9ea..2db32b9b8 100644
--- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC331Test.php
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC331Test.php
@@ -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())
+ );
}
}
\ No newline at end of file
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC448Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC448Test.php
index f0867f352..4ea830863 100644
--- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC448Test.php
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC448Test.php
@@ -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())
+ );
}
}
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC493Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC493Test.php
index 25f378255..9e8d58be9 100644
--- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC493Test.php
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC493Test.php
@@ -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())
+ );
}
}
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC513Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC513Test.php
index 125f297db..b71d674cc 100644
--- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC513Test.php
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC513Test.php
@@ -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())
+ );
}
}
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC698Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC698Test.php
index 9fbfd01ab..4786cc176 100644
--- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC698Test.php
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC698Test.php
@@ -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)
+ );
}
}
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC719Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC719Test.php
index 82cb67223..6bd18ef98 100644
--- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC719Test.php
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC719Test.php
@@ -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; }
}
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC949Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC949Test.php
index 473a8679f..a3734b75a 100644
--- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC949Test.php
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC949Test.php
@@ -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.");
}
}
\ No newline at end of file
diff --git a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php
index 53002a8fc..499fb8c4c 100644
--- a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php
+++ b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php
@@ -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
*/
@@ -604,7 +604,24 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
. ' WHERE EXISTS ('
. 'SELECT c1_.id FROM cms_employees c1_ WHERE c1_.id = c0_.spouse_id'
. ')'
+ );
+ }
+ public function testExistsExpressionWithSimpleSelectReturningScalar()
+ {
+ $this->assertSqlGeneration(
+ // DQL
+ // The result of this query consists of all employees whose spouses are also employees.
+ 'SELECT DISTINCT emp FROM Doctrine\Tests\Models\CMS\CmsEmployee emp
+ WHERE EXISTS (
+ SELECT 1
+ FROM Doctrine\Tests\Models\CMS\CmsEmployee spouseEmp
+ WHERE spouseEmp = emp.spouse)',
+ // SQL
+ 'SELECT DISTINCT c0_.id AS id0, c0_.name AS name1 FROM cms_employees c0_'
+ . ' WHERE EXISTS ('
+ . 'SELECT 1 AS sclr2 FROM cms_employees c1_ WHERE c1_.id = c0_.spouse_id'
+ . ')'
);
}
@@ -686,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(
@@ -694,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
*/
@@ -729,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);
@@ -877,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)
);
@@ -931,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(
@@ -939,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(
@@ -1009,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 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',
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 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',
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 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",
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)"
+ );
+ }
}
@@ -1277,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;
+}
diff --git a/tests/Doctrine/Tests/ORM/Tools/SchemaValidatorTest.php b/tests/Doctrine/Tests/ORM/Tools/SchemaValidatorTest.php
index 64bb03f36..0fc3bb636 100644
--- a/tests/Doctrine/Tests/ORM/Tools/SchemaValidatorTest.php
+++ b/tests/Doctrine/Tests/ORM/Tools/SchemaValidatorTest.php
@@ -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;
}
\ No newline at end of file