Merge branch 'master' of github.com:doctrine/doctrine2
This commit is contained in:
commit
7841ccb7c0
@ -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
|
# EntityManager#getPartialReference() creates read-only entity
|
||||||
|
|
||||||
Entities returned from EntityManager#getPartialReference() are now marked as read-only if they
|
Entities returned from EntityManager#getPartialReference() are now marked as read-only if they
|
||||||
|
@ -20,7 +20,8 @@
|
|||||||
namespace Doctrine\ORM;
|
namespace Doctrine\ORM;
|
||||||
|
|
||||||
use Doctrine\DBAL\Types\Type,
|
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.
|
* Base contract for ORM queries. Base class for Query and NativeQuery.
|
||||||
@ -91,34 +92,15 @@ abstract class AbstractQuery
|
|||||||
protected $_hydrationMode = self::HYDRATE_OBJECT;
|
protected $_hydrationMode = self::HYDRATE_OBJECT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The locally set cache driver used for caching result sets of this query.
|
* @param \Doctrine\DBAL\Cache\QueryCacheProfile
|
||||||
*
|
|
||||||
* @var CacheDriver
|
|
||||||
*/
|
*/
|
||||||
protected $_resultCacheDriver;
|
protected $_queryCacheProfile;
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var boolean Boolean value that indicates whether or not expire the result cache.
|
* @var boolean Boolean value that indicates whether or not expire the result cache.
|
||||||
*/
|
*/
|
||||||
protected $_expireResultCache = false;
|
protected $_expireResultCache = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int Result Cache lifetime.
|
|
||||||
*/
|
|
||||||
protected $_resultCacheTTL;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new instance of a class derived from <tt>AbstractQuery</tt>.
|
* Initializes a new instance of a class derived from <tt>AbstractQuery</tt>.
|
||||||
*
|
*
|
||||||
@ -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
|
* @param Doctrine\Common\Cache\Cache $driver Cache driver
|
||||||
* @return Doctrine\ORM\AbstractQuery
|
* @return Doctrine\ORM\AbstractQuery
|
||||||
@ -270,9 +252,10 @@ abstract class AbstractQuery
|
|||||||
if ($resultCacheDriver !== null && ! ($resultCacheDriver instanceof \Doctrine\Common\Cache\Cache)) {
|
if ($resultCacheDriver !== null && ! ($resultCacheDriver instanceof \Doctrine\Common\Cache\Cache)) {
|
||||||
throw ORMException::invalidResultCacheDriver();
|
throw ORMException::invalidResultCacheDriver();
|
||||||
}
|
}
|
||||||
$this->_resultCacheDriver = $resultCacheDriver;
|
if ($this->_queryCacheProfile) {
|
||||||
if ($resultCacheDriver) {
|
$this->_queryCacheProfile = $this->_queryCacheProfile->setResultCacheDriver($resultCacheDriver);
|
||||||
$this->_useResultCache = true;
|
} else {
|
||||||
|
$this->_queryCacheProfile = new QueryCacheProfile(0, null, $resultCacheDriver);
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -280,12 +263,13 @@ abstract class AbstractQuery
|
|||||||
/**
|
/**
|
||||||
* Returns the cache driver used for caching result sets.
|
* Returns the cache driver used for caching result sets.
|
||||||
*
|
*
|
||||||
|
* @deprecated
|
||||||
* @return Doctrine\Common\Cache\Cache Cache driver
|
* @return Doctrine\Common\Cache\Cache Cache driver
|
||||||
*/
|
*/
|
||||||
public function getResultCacheDriver()
|
public function getResultCacheDriver()
|
||||||
{
|
{
|
||||||
if ($this->_resultCacheDriver) {
|
if ($this->_queryCacheProfile && $this->_queryCacheProfile->getResultCacheDriver()) {
|
||||||
return $this->_resultCacheDriver;
|
return $this->_queryCacheProfile->getResultCacheDriver();
|
||||||
} else {
|
} else {
|
||||||
return $this->_em->getConfiguration()->getResultCacheImpl();
|
return $this->_em->getConfiguration()->getResultCacheImpl();
|
||||||
}
|
}
|
||||||
@ -296,18 +280,17 @@ abstract class AbstractQuery
|
|||||||
* how long and which ID to use for the cache entry.
|
* how long and which ID to use for the cache entry.
|
||||||
*
|
*
|
||||||
* @param boolean $bool
|
* @param boolean $bool
|
||||||
* @param integer $timeToLive
|
* @param integer $lifetime
|
||||||
* @param string $resultCacheId
|
* @param string $resultCacheId
|
||||||
* @return Doctrine\ORM\AbstractQuery This query instance.
|
* @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 ($bool) {
|
||||||
if ($timeToLive) {
|
$this->setResultCacheLifetime($lifetime);
|
||||||
$this->setResultCacheLifetime($timeToLive);
|
$this->setResultCacheId($resultCacheId);
|
||||||
}
|
} else {
|
||||||
if ($resultCacheId) {
|
$this->_queryCacheProfile = null;
|
||||||
$this->_resultCacheId = $resultCacheId;
|
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -315,27 +298,33 @@ abstract class AbstractQuery
|
|||||||
/**
|
/**
|
||||||
* Defines how long the result cache will be active before expire.
|
* 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.
|
* @return Doctrine\ORM\AbstractQuery This query instance.
|
||||||
*/
|
*/
|
||||||
public function setResultCacheLifetime($timeToLive)
|
public function setResultCacheLifetime($lifetime)
|
||||||
{
|
{
|
||||||
if ($timeToLive !== null) {
|
if ($lifetime === null) {
|
||||||
$timeToLive = (int) $timeToLive;
|
$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;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the lifetime of resultset cache.
|
* Retrieves the lifetime of resultset cache.
|
||||||
*
|
*
|
||||||
|
* @deprecated
|
||||||
* @return integer
|
* @return integer
|
||||||
*/
|
*/
|
||||||
public function getResultCacheLifetime()
|
public function getResultCacheLifetime()
|
||||||
{
|
{
|
||||||
return $this->_resultCacheTTL;
|
return $this->_queryCacheProfile ? $this->_queryCacheProfile->getLifetime() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -360,6 +349,14 @@ abstract class AbstractQuery
|
|||||||
return $this->_expireResultCache;
|
return $this->_expireResultCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return QueryCacheProfile
|
||||||
|
*/
|
||||||
|
public function getQueryCacheProfile()
|
||||||
|
{
|
||||||
|
return $this->_queryCacheProfile;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the default fetch mode of an association for this query.
|
* Change the default fetch mode of an association for this query.
|
||||||
*
|
*
|
||||||
@ -584,28 +581,6 @@ abstract class AbstractQuery
|
|||||||
$this->setParameters($params);
|
$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();
|
$stmt = $this->_doExecute();
|
||||||
|
|
||||||
if (is_numeric($stmt)) {
|
if (is_numeric($stmt)) {
|
||||||
@ -627,43 +602,23 @@ abstract class AbstractQuery
|
|||||||
*/
|
*/
|
||||||
public function setResultCacheId($id)
|
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;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the result cache id to use to store the result set cache entry.
|
* Get the result cache id to use to store the result set cache entry if set.
|
||||||
* Will return the configured id if it exists otherwise a hash will be
|
|
||||||
* automatically generated for you.
|
|
||||||
*
|
*
|
||||||
* @return array ($key, $hash)
|
* @deprecated
|
||||||
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function getResultCacheId()
|
public function getResultCacheId()
|
||||||
{
|
{
|
||||||
if ($this->_resultCacheId) {
|
return $this->_queryCacheProfile ? $this->_queryCacheProfile->getCacheKey() : null;
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -209,27 +209,6 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
|||||||
$this->_attributes['metadataDriverImpl'] : null;
|
$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).
|
* Gets the cache driver implementation that is used for the query cache (SQL cache).
|
||||||
*
|
*
|
||||||
|
@ -57,17 +57,17 @@ final class NativeQuery extends AbstractQuery
|
|||||||
*/
|
*/
|
||||||
protected function _doExecute()
|
protected function _doExecute()
|
||||||
{
|
{
|
||||||
$stmt = $this->_em->getConnection()->prepare($this->_sql);
|
|
||||||
$params = $this->_params;
|
$params = $this->_params;
|
||||||
foreach ($params as $key => $value) {
|
$types = $this->_paramTypes;
|
||||||
if (isset($this->_paramTypes[$key])) {
|
if ($params) {
|
||||||
$stmt->bindValue($key, $value, $this->_paramTypes[$key]);
|
if (is_int(key($params))) {
|
||||||
} else {
|
ksort($params);
|
||||||
$stmt->bindValue($key, $value);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -92,7 +92,7 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The database platform.
|
* The database platform.
|
||||||
*
|
*
|
||||||
* @var Doctrine\DBAL\Platforms\AbstractPlatform
|
* @var Doctrine\DBAL\Platforms\AbstractPlatform
|
||||||
*/
|
*/
|
||||||
protected $_platform;
|
protected $_platform;
|
||||||
@ -110,12 +110,12 @@ class BasicEntityPersister
|
|||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $_queuedInserts = array();
|
protected $_queuedInserts = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ResultSetMapping that is used for all queries. Is generated lazily once per request.
|
* ResultSetMapping that is used for all queries. Is generated lazily once per request.
|
||||||
*
|
*
|
||||||
* TODO: Evaluate Caching in combination with the other cached SQL snippets.
|
* TODO: Evaluate Caching in combination with the other cached SQL snippets.
|
||||||
*
|
*
|
||||||
* @var Query\ResultSetMapping
|
* @var Query\ResultSetMapping
|
||||||
*/
|
*/
|
||||||
protected $_rsm;
|
protected $_rsm;
|
||||||
@ -123,7 +123,7 @@ class BasicEntityPersister
|
|||||||
/**
|
/**
|
||||||
* The map of column names to DBAL mapping types of all prepared columns used
|
* The map of column names to DBAL mapping types of all prepared columns used
|
||||||
* when INSERTing or UPDATEing an entity.
|
* when INSERTing or UPDATEing an entity.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
* @see _prepareInsertData($entity)
|
* @see _prepareInsertData($entity)
|
||||||
* @see _prepareUpdateData($entity)
|
* @see _prepareUpdateData($entity)
|
||||||
@ -133,7 +133,7 @@ class BasicEntityPersister
|
|||||||
/**
|
/**
|
||||||
* The INSERT SQL statement used for entities handled by this persister.
|
* The INSERT SQL statement used for entities handled by this persister.
|
||||||
* This SQL is only generated once per request, if at all.
|
* This SQL is only generated once per request, if at all.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $_insertSql;
|
private $_insertSql;
|
||||||
@ -141,29 +141,29 @@ class BasicEntityPersister
|
|||||||
/**
|
/**
|
||||||
* The SELECT column list SQL fragment used for querying entities by this persister.
|
* 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.
|
* This SQL fragment is only generated once per request, if at all.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $_selectColumnListSql;
|
protected $_selectColumnListSql;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The JOIN SQL fragement used to eagerly load all many-to-one and one-to-one
|
* 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.
|
* associations configured as FETCH_EAGER, aswell as all inverse one-to-one associations.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $_selectJoinSql;
|
protected $_selectJoinSql;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counter for creating unique SQL table and column aliases.
|
* Counter for creating unique SQL table and column aliases.
|
||||||
*
|
*
|
||||||
* @var integer
|
* @var integer
|
||||||
*/
|
*/
|
||||||
protected $_sqlAliasCounter = 0;
|
protected $_sqlAliasCounter = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map from class names (FQCN) to the corresponding generated SQL table aliases.
|
* Map from class names (FQCN) to the corresponding generated SQL table aliases.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $_sqlTableAliases = array();
|
protected $_sqlTableAliases = array();
|
||||||
@ -171,7 +171,7 @@ class BasicEntityPersister
|
|||||||
/**
|
/**
|
||||||
* Initializes a new <tt>BasicEntityPersister</tt> that uses the given EntityManager
|
* Initializes a new <tt>BasicEntityPersister</tt> that uses the given EntityManager
|
||||||
* and persists instances of the class described by the given ClassMetadata descriptor.
|
* and persists instances of the class described by the given ClassMetadata descriptor.
|
||||||
*
|
*
|
||||||
* @param Doctrine\ORM\EntityManager $em
|
* @param Doctrine\ORM\EntityManager $em
|
||||||
* @param Doctrine\ORM\Mapping\ClassMetadata $class
|
* @param Doctrine\ORM\Mapping\ClassMetadata $class
|
||||||
*/
|
*/
|
||||||
@ -205,7 +205,7 @@ class BasicEntityPersister
|
|||||||
/**
|
/**
|
||||||
* Executes all queued entity insertions and returns any generated post-insert
|
* Executes all queued entity insertions and returns any generated post-insert
|
||||||
* identifiers that were created as a result of the insertions.
|
* identifiers that were created as a result of the insertions.
|
||||||
*
|
*
|
||||||
* If no inserts are queued, invoking this method is a NOOP.
|
* 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
|
* @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])) {
|
if (isset($insertData[$tableName])) {
|
||||||
$paramIndex = 1;
|
$paramIndex = 1;
|
||||||
|
|
||||||
foreach ($insertData[$tableName] as $column => $value) {
|
foreach ($insertData[$tableName] as $column => $value) {
|
||||||
$stmt->bindValue($paramIndex++, $value, $this->_columnTypes[$column]);
|
$stmt->bindValue($paramIndex++, $value, $this->_columnTypes[$column]);
|
||||||
}
|
}
|
||||||
@ -257,7 +257,7 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the default version value which was created
|
* 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.
|
* entities version field.
|
||||||
*
|
*
|
||||||
* @param object $entity
|
* @param object $entity
|
||||||
@ -271,7 +271,7 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch the current version value of a versioned entity.
|
* Fetch the current version value of a versioned entity.
|
||||||
*
|
*
|
||||||
* @param Doctrine\ORM\Mapping\ClassMetadata $versionedClass
|
* @param Doctrine\ORM\Mapping\ClassMetadata $versionedClass
|
||||||
* @param mixed $id
|
* @param mixed $id
|
||||||
* @return mixed
|
* @return mixed
|
||||||
@ -280,9 +280,9 @@ class BasicEntityPersister
|
|||||||
{
|
{
|
||||||
$versionField = $versionedClass->versionField;
|
$versionField = $versionedClass->versionField;
|
||||||
$identifier = $versionedClass->getIdentifierColumnNames();
|
$identifier = $versionedClass->getIdentifierColumnNames();
|
||||||
|
|
||||||
$versionFieldColumnName = $versionedClass->getQuotedColumnName($versionField, $this->_platform);
|
$versionFieldColumnName = $versionedClass->getQuotedColumnName($versionField, $this->_platform);
|
||||||
|
|
||||||
//FIXME: Order with composite keys might not be correct
|
//FIXME: Order with composite keys might not be correct
|
||||||
$sql = 'SELECT ' . $versionFieldColumnName
|
$sql = 'SELECT ' . $versionFieldColumnName
|
||||||
. ' FROM ' . $versionedClass->getQuotedTableName($this->_platform)
|
. ' FROM ' . $versionedClass->getQuotedTableName($this->_platform)
|
||||||
@ -299,7 +299,7 @@ class BasicEntityPersister
|
|||||||
* The data to update is retrieved through {@link _prepareUpdateData}.
|
* The data to update is retrieved through {@link _prepareUpdateData}.
|
||||||
* Subclasses that override this method are supposed to obtain the update data
|
* Subclasses that override this method are supposed to obtain the update data
|
||||||
* in the same way, through {@link _prepareUpdateData}.
|
* in the same way, through {@link _prepareUpdateData}.
|
||||||
*
|
*
|
||||||
* Subclasses are also supposed to take care of versioning when overriding this method,
|
* 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
|
* if necessary. The {@link _updateTable} method can be used to apply the data retrieved
|
||||||
* from {@_prepareUpdateData} on the target tables, thereby optionally applying versioning.
|
* from {@_prepareUpdateData} on the target tables, thereby optionally applying versioning.
|
||||||
@ -310,7 +310,7 @@ class BasicEntityPersister
|
|||||||
{
|
{
|
||||||
$updateData = $this->_prepareUpdateData($entity);
|
$updateData = $this->_prepareUpdateData($entity);
|
||||||
$tableName = $this->_class->getTableName();
|
$tableName = $this->_class->getTableName();
|
||||||
|
|
||||||
if (isset($updateData[$tableName]) && $updateData[$tableName]) {
|
if (isset($updateData[$tableName]) && $updateData[$tableName]) {
|
||||||
$this->_updateTable(
|
$this->_updateTable(
|
||||||
$entity, $this->_class->getQuotedTableName($this->_platform),
|
$entity, $this->_class->getQuotedTableName($this->_platform),
|
||||||
@ -338,17 +338,17 @@ class BasicEntityPersister
|
|||||||
$set = $params = $types = array();
|
$set = $params = $types = array();
|
||||||
|
|
||||||
foreach ($updateData as $columnName => $value) {
|
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) . ' = ?'
|
? $this->_class->getQuotedColumnName($this->_class->fieldNames[$columnName], $this->_platform) . ' = ?'
|
||||||
: $columnName . ' = ?';
|
: $columnName . ' = ?';
|
||||||
|
|
||||||
$params[] = $value;
|
$params[] = $value;
|
||||||
$types[] = $this->_columnTypes[$columnName];
|
$types[] = $this->_columnTypes[$columnName];
|
||||||
}
|
}
|
||||||
|
|
||||||
$where = array();
|
$where = array();
|
||||||
$id = $this->_em->getUnitOfWork()->getEntityIdentifier($entity);
|
$id = $this->_em->getUnitOfWork()->getEntityIdentifier($entity);
|
||||||
|
|
||||||
foreach ($this->_class->identifier as $idField) {
|
foreach ($this->_class->identifier as $idField) {
|
||||||
if (isset($this->_class->associationMappings[$idField])) {
|
if (isset($this->_class->associationMappings[$idField])) {
|
||||||
$targetMapping = $this->_em->getClassMetadata($this->_class->associationMappings[$idField]['targetEntity']);
|
$targetMapping = $this->_em->getClassMetadata($this->_class->associationMappings[$idField]['targetEntity']);
|
||||||
@ -366,13 +366,13 @@ class BasicEntityPersister
|
|||||||
$versionField = $this->_class->versionField;
|
$versionField = $this->_class->versionField;
|
||||||
$versionFieldType = $this->_class->fieldMappings[$versionField]['type'];
|
$versionFieldType = $this->_class->fieldMappings[$versionField]['type'];
|
||||||
$versionColumn = $this->_class->getQuotedColumnName($versionField, $this->_platform);
|
$versionColumn = $this->_class->getQuotedColumnName($versionField, $this->_platform);
|
||||||
|
|
||||||
if ($versionFieldType == Type::INTEGER) {
|
if ($versionFieldType == Type::INTEGER) {
|
||||||
$set[] = $versionColumn . ' = ' . $versionColumn . ' + 1';
|
$set[] = $versionColumn . ' = ' . $versionColumn . ' + 1';
|
||||||
} else if ($versionFieldType == Type::DATETIME) {
|
} else if ($versionFieldType == Type::DATETIME) {
|
||||||
$set[] = $versionColumn . ' = CURRENT_TIMESTAMP';
|
$set[] = $versionColumn . ' = CURRENT_TIMESTAMP';
|
||||||
}
|
}
|
||||||
|
|
||||||
$where[] = $versionColumn;
|
$where[] = $versionColumn;
|
||||||
$params[] = $this->_class->reflFields[$versionField]->getValue($entity);
|
$params[] = $this->_class->reflFields[$versionField]->getValue($entity);
|
||||||
$types[] = $this->_class->fieldMappings[$versionField]['type'];
|
$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
|
// @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!
|
// like self-referential relationship between different levels of an inheritance hierachy? I hope not!
|
||||||
$selfReferential = ($mapping['targetEntity'] == $mapping['sourceEntity']);
|
$selfReferential = ($mapping['targetEntity'] == $mapping['sourceEntity']);
|
||||||
|
|
||||||
if ( ! $mapping['isOwningSide']) {
|
if ( ! $mapping['isOwningSide']) {
|
||||||
$relatedClass = $this->_em->getClassMetadata($mapping['targetEntity']);
|
$relatedClass = $this->_em->getClassMetadata($mapping['targetEntity']);
|
||||||
$mapping = $relatedClass->associationMappings[$mapping['mappedBy']];
|
$mapping = $relatedClass->associationMappings[$mapping['mappedBy']];
|
||||||
$keys = array_keys($mapping['relationToTargetKeyColumns']);
|
$keys = array_keys($mapping['relationToTargetKeyColumns']);
|
||||||
|
|
||||||
if ($selfReferential) {
|
if ($selfReferential) {
|
||||||
$otherKeys = array_keys($mapping['relationToSourceKeyColumns']);
|
$otherKeys = array_keys($mapping['relationToSourceKeyColumns']);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$keys = array_keys($mapping['relationToSourceKeyColumns']);
|
$keys = array_keys($mapping['relationToSourceKeyColumns']);
|
||||||
|
|
||||||
if ($selfReferential) {
|
if ($selfReferential) {
|
||||||
$otherKeys = array_keys($mapping['relationToTargetKeyColumns']);
|
$otherKeys = array_keys($mapping['relationToTargetKeyColumns']);
|
||||||
}
|
}
|
||||||
@ -420,13 +420,13 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
if ( ! isset($mapping['isOnDeleteCascade'])) {
|
if ( ! isset($mapping['isOnDeleteCascade'])) {
|
||||||
$this->_conn->delete(
|
$this->_conn->delete(
|
||||||
$this->_class->getQuotedJoinTableName($mapping, $this->_platform),
|
$this->_class->getQuotedJoinTableName($mapping, $this->_platform),
|
||||||
array_combine($keys, $identifier)
|
array_combine($keys, $identifier)
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($selfReferential) {
|
if ($selfReferential) {
|
||||||
$this->_conn->delete(
|
$this->_conn->delete(
|
||||||
$this->_class->getQuotedJoinTableName($mapping, $this->_platform),
|
$this->_class->getQuotedJoinTableName($mapping, $this->_platform),
|
||||||
array_combine($otherKeys, $identifier)
|
array_combine($otherKeys, $identifier)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -458,7 +458,7 @@ class BasicEntityPersister
|
|||||||
* Prepares the changeset of an entity for database insertion (UPDATE).
|
* Prepares the changeset of an entity for database insertion (UPDATE).
|
||||||
*
|
*
|
||||||
* The changeset is obtained from the currently running UnitOfWork.
|
* The changeset is obtained from the currently running UnitOfWork.
|
||||||
*
|
*
|
||||||
* During this preparation the array that is passed as the second parameter is filled with
|
* During this preparation the array that is passed as the second parameter is filled with
|
||||||
* <columnName> => <value> pairs, grouped by table name.
|
* <columnName> => <value> pairs, grouped by table name.
|
||||||
*
|
*
|
||||||
@ -493,7 +493,7 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
if (isset($this->_class->associationMappings[$field])) {
|
if (isset($this->_class->associationMappings[$field])) {
|
||||||
$assoc = $this->_class->associationMappings[$field];
|
$assoc = $this->_class->associationMappings[$field];
|
||||||
|
|
||||||
// Only owning side of x-1 associations can have a FK column.
|
// Only owning side of x-1 associations can have a FK column.
|
||||||
if ( ! $assoc['isOwningSide'] || ! ($assoc['type'] & ClassMetadata::TO_ONE)) {
|
if ( ! $assoc['isOwningSide'] || ! ($assoc['type'] & ClassMetadata::TO_ONE)) {
|
||||||
continue;
|
continue;
|
||||||
@ -501,7 +501,7 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
if ($newVal !== null) {
|
if ($newVal !== null) {
|
||||||
$oid = spl_object_hash($newVal);
|
$oid = spl_object_hash($newVal);
|
||||||
|
|
||||||
if (isset($this->_queuedInserts[$oid]) || $uow->isScheduledForInsert($newVal)) {
|
if (isset($this->_queuedInserts[$oid]) || $uow->isScheduledForInsert($newVal)) {
|
||||||
// The associated entity $newVal is not yet persisted, so we must
|
// The associated entity $newVal is not yet persisted, so we must
|
||||||
// set $newVal = null, in order to insert a null value and schedule an
|
// set $newVal = null, in order to insert a null value and schedule an
|
||||||
@ -528,7 +528,7 @@ class BasicEntityPersister
|
|||||||
} else {
|
} else {
|
||||||
$result[$owningTable][$sourceColumn] = $newValId[$targetClass->fieldNames[$targetColumn]];
|
$result[$owningTable][$sourceColumn] = $newValId[$targetClass->fieldNames[$targetColumn]];
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_columnTypes[$sourceColumn] = $targetClass->getTypeOfColumn($targetColumn);
|
$this->_columnTypes[$sourceColumn] = $targetClass->getTypeOfColumn($targetColumn);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -537,7 +537,7 @@ class BasicEntityPersister
|
|||||||
$result[$this->getOwningTable($field)][$columnName] = $newVal;
|
$result[$this->getOwningTable($field)][$columnName] = $newVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,7 +589,7 @@ class BasicEntityPersister
|
|||||||
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc, $lockMode, $limit);
|
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc, $lockMode, $limit);
|
||||||
list($params, $types) = $this->expandParameters($criteria);
|
list($params, $types) = $this->expandParameters($criteria);
|
||||||
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
||||||
|
|
||||||
if ($entity !== null) {
|
if ($entity !== null) {
|
||||||
$hints[Query::HINT_REFRESH] = true;
|
$hints[Query::HINT_REFRESH] = true;
|
||||||
$hints[Query::HINT_REFRESH_ENTITY] = $entity;
|
$hints[Query::HINT_REFRESH_ENTITY] = $entity;
|
||||||
@ -597,7 +597,7 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
$hydrator = $this->_em->newHydrator($this->_selectJoinSql ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT);
|
$hydrator = $this->_em->newHydrator($this->_selectJoinSql ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT);
|
||||||
$entities = $hydrator->hydrateAll($stmt, $this->_rsm, $hints);
|
$entities = $hydrator->hydrateAll($stmt, $this->_rsm, $hints);
|
||||||
|
|
||||||
return $entities ? $entities[0] : null;
|
return $entities ? $entities[0] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -626,17 +626,17 @@ class BasicEntityPersister
|
|||||||
// Mark inverse side as fetched in the hints, otherwise the UoW would
|
// 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).
|
// try to load it in a separate query (remember: to-one inverse sides can not be lazy).
|
||||||
$hints = array();
|
$hints = array();
|
||||||
|
|
||||||
if ($isInverseSingleValued) {
|
if ($isInverseSingleValued) {
|
||||||
$hints['fetched'][$targetClass->name][$assoc['inversedBy']] = true;
|
$hints['fetched'][$targetClass->name][$assoc['inversedBy']] = true;
|
||||||
|
|
||||||
if ($targetClass->subClasses) {
|
if ($targetClass->subClasses) {
|
||||||
foreach ($targetClass->subClasses as $targetSubclassName) {
|
foreach ($targetClass->subClasses as $targetSubclassName) {
|
||||||
$hints['fetched'][$targetSubclassName][$assoc['inversedBy']] = true;
|
$hints['fetched'][$targetSubclassName][$assoc['inversedBy']] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cascade read-only status
|
/* cascade read-only status
|
||||||
if ($this->_em->getUnitOfWork()->isReadOnly($sourceEntity)) {
|
if ($this->_em->getUnitOfWork()->isReadOnly($sourceEntity)) {
|
||||||
$hints[Query::HINT_READ_ONLY] = true;
|
$hints[Query::HINT_READ_ONLY] = true;
|
||||||
@ -652,7 +652,7 @@ class BasicEntityPersister
|
|||||||
} else {
|
} else {
|
||||||
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
|
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
|
||||||
$owningAssoc = $targetClass->getAssociationMapping($assoc['mappedBy']);
|
$owningAssoc = $targetClass->getAssociationMapping($assoc['mappedBy']);
|
||||||
|
|
||||||
// TRICKY: since the association is specular source and target are flipped
|
// TRICKY: since the association is specular source and target are flipped
|
||||||
foreach ($owningAssoc['targetToSourceKeyColumns'] as $sourceKeyColumn => $targetKeyColumn) {
|
foreach ($owningAssoc['targetToSourceKeyColumns'] as $sourceKeyColumn => $targetKeyColumn) {
|
||||||
if ( ! isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
if ( ! isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
||||||
@ -660,12 +660,12 @@ class BasicEntityPersister
|
|||||||
$sourceClass->name, $sourceKeyColumn
|
$sourceClass->name, $sourceKeyColumn
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// unset the old value and set the new sql aliased value here. By definition
|
// 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.
|
// unset($identifier[$targetKeyColumn] works here with how UnitOfWork::createEntity() calls this method.
|
||||||
$identifier[$this->_getSQLTableAlias($targetClass->name) . "." . $targetKeyColumn] =
|
$identifier[$this->_getSQLTableAlias($targetClass->name) . "." . $targetKeyColumn] =
|
||||||
$sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
$sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||||
|
|
||||||
unset($identifier[$targetKeyColumn]);
|
unset($identifier[$targetKeyColumn]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -681,7 +681,7 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Refreshes a managed entity.
|
* Refreshes a managed entity.
|
||||||
*
|
*
|
||||||
* @param array $id The identifier of the entity as an associative array from
|
* @param array $id The identifier of the entity as an associative array from
|
||||||
* column or field names to values.
|
* column or field names to values.
|
||||||
* @param object $entity The entity to refresh.
|
* @param object $entity The entity to refresh.
|
||||||
@ -691,16 +691,16 @@ class BasicEntityPersister
|
|||||||
$sql = $this->_getSelectEntitiesSQL($id);
|
$sql = $this->_getSelectEntitiesSQL($id);
|
||||||
list($params, $types) = $this->expandParameters($id);
|
list($params, $types) = $this->expandParameters($id);
|
||||||
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
||||||
|
|
||||||
$hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT);
|
$hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT);
|
||||||
$hydrator->hydrateAll($stmt, $this->_rsm, array(Query::HINT_REFRESH => true));
|
$hydrator->hydrateAll($stmt, $this->_rsm, array(Query::HINT_REFRESH => true));
|
||||||
|
|
||||||
if (isset($this->_class->lifecycleCallbacks[Events::postLoad])) {
|
if (isset($this->_class->lifecycleCallbacks[Events::postLoad])) {
|
||||||
$this->_class->invokeLifecycleCallbacks(Events::postLoad, $entity);
|
$this->_class->invokeLifecycleCallbacks(Events::postLoad, $entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
$evm = $this->_em->getEventManager();
|
$evm = $this->_em->getEventManager();
|
||||||
|
|
||||||
if ($evm->hasListeners(Events::postLoad)) {
|
if ($evm->hasListeners(Events::postLoad)) {
|
||||||
$evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity, $this->_em));
|
$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.
|
* Loads a list of entities by a list of field criteria.
|
||||||
*
|
*
|
||||||
* @param array $criteria
|
* @param array $criteria
|
||||||
* @param array $orderBy
|
* @param array $orderBy
|
||||||
* @param int $limit
|
* @param int $limit
|
||||||
@ -723,13 +723,13 @@ class BasicEntityPersister
|
|||||||
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
||||||
|
|
||||||
$hydrator = $this->_em->newHydrator(($this->_selectJoinSql) ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT);
|
$hydrator = $this->_em->newHydrator(($this->_selectJoinSql) ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT);
|
||||||
|
|
||||||
return $hydrator->hydrateAll($stmt, $this->_rsm, array('deferEagerLoads' => true));
|
return $hydrator->hydrateAll($stmt, $this->_rsm, array('deferEagerLoads' => true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get (sliced or full) elements of the given collection.
|
* Get (sliced or full) elements of the given collection.
|
||||||
*
|
*
|
||||||
* @param array $assoc
|
* @param array $assoc
|
||||||
* @param object $sourceEntity
|
* @param object $sourceEntity
|
||||||
* @param int|null $offset
|
* @param int|null $offset
|
||||||
@ -739,16 +739,16 @@ class BasicEntityPersister
|
|||||||
public function getManyToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null)
|
public function getManyToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null)
|
||||||
{
|
{
|
||||||
$stmt = $this->getManyToManyStatement($assoc, $sourceEntity, $offset, $limit);
|
$stmt = $this->getManyToManyStatement($assoc, $sourceEntity, $offset, $limit);
|
||||||
|
|
||||||
return $this->loadArrayFromStatement($assoc, $stmt);
|
return $this->loadArrayFromStatement($assoc, $stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load an array of entities from a given dbal statement.
|
* Load an array of entities from a given dbal statement.
|
||||||
*
|
*
|
||||||
* @param array $assoc
|
* @param array $assoc
|
||||||
* @param Doctrine\DBAL\Statement $stmt
|
* @param Doctrine\DBAL\Statement $stmt
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function loadArrayFromStatement($assoc, $stmt)
|
private function loadArrayFromStatement($assoc, $stmt)
|
||||||
@ -763,21 +763,21 @@ class BasicEntityPersister
|
|||||||
}
|
}
|
||||||
|
|
||||||
$hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT);
|
$hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT);
|
||||||
|
|
||||||
return $hydrator->hydrateAll($stmt, $rsm, $hints);
|
return $hydrator->hydrateAll($stmt, $rsm, $hints);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hydrate a collection from a given dbal statement.
|
* Hydrate a collection from a given dbal statement.
|
||||||
*
|
*
|
||||||
* @param array $assoc
|
* @param array $assoc
|
||||||
* @param Doctrine\DBAL\Statement $stmt
|
* @param Doctrine\DBAL\Statement $stmt
|
||||||
* @param PersistentCollection $coll
|
* @param PersistentCollection $coll
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function loadCollectionFromStatement($assoc, $stmt, $coll)
|
private function loadCollectionFromStatement($assoc, $stmt, $coll)
|
||||||
{
|
{
|
||||||
$hints = array('deferEagerLoads' => true, 'collection' => $coll);
|
$hints = array('deferEagerLoads' => true, 'collection' => $coll);
|
||||||
|
|
||||||
if (isset($assoc['indexBy'])) {
|
if (isset($assoc['indexBy'])) {
|
||||||
@ -788,7 +788,7 @@ class BasicEntityPersister
|
|||||||
}
|
}
|
||||||
|
|
||||||
$hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT);
|
$hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT);
|
||||||
|
|
||||||
return $hydrator->hydrateAll($stmt, $rsm, $hints);
|
return $hydrator->hydrateAll($stmt, $rsm, $hints);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -805,7 +805,7 @@ class BasicEntityPersister
|
|||||||
public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
|
public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
|
||||||
{
|
{
|
||||||
$stmt = $this->getManyToManyStatement($assoc, $sourceEntity);
|
$stmt = $this->getManyToManyStatement($assoc, $sourceEntity);
|
||||||
|
|
||||||
return $this->loadCollectionFromStatement($assoc, $stmt, $coll);
|
return $this->loadCollectionFromStatement($assoc, $stmt, $coll);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -813,15 +813,15 @@ class BasicEntityPersister
|
|||||||
{
|
{
|
||||||
$criteria = array();
|
$criteria = array();
|
||||||
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
|
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
|
||||||
|
|
||||||
if ($assoc['isOwningSide']) {
|
if ($assoc['isOwningSide']) {
|
||||||
$quotedJoinTable = $sourceClass->getQuotedJoinTableName($assoc, $this->_platform);
|
$quotedJoinTable = $sourceClass->getQuotedJoinTableName($assoc, $this->_platform);
|
||||||
|
|
||||||
foreach ($assoc['relationToSourceKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
|
foreach ($assoc['relationToSourceKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
|
||||||
if ($sourceClass->containsForeignIdentifier) {
|
if ($sourceClass->containsForeignIdentifier) {
|
||||||
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
|
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
|
||||||
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
|
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
|
||||||
|
|
||||||
if (isset($sourceClass->associationMappings[$field])) {
|
if (isset($sourceClass->associationMappings[$field])) {
|
||||||
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
||||||
$value = $value[$this->_em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]];
|
$value = $value[$this->_em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]];
|
||||||
@ -839,18 +839,18 @@ class BasicEntityPersister
|
|||||||
} else {
|
} else {
|
||||||
$owningAssoc = $this->_em->getClassMetadata($assoc['targetEntity'])->associationMappings[$assoc['mappedBy']];
|
$owningAssoc = $this->_em->getClassMetadata($assoc['targetEntity'])->associationMappings[$assoc['mappedBy']];
|
||||||
$quotedJoinTable = $sourceClass->getQuotedJoinTableName($owningAssoc, $this->_platform);
|
$quotedJoinTable = $sourceClass->getQuotedJoinTableName($owningAssoc, $this->_platform);
|
||||||
|
|
||||||
// TRICKY: since the association is inverted source and target are flipped
|
// TRICKY: since the association is inverted source and target are flipped
|
||||||
foreach ($owningAssoc['relationToTargetKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
|
foreach ($owningAssoc['relationToTargetKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
|
||||||
if ($sourceClass->containsForeignIdentifier) {
|
if ($sourceClass->containsForeignIdentifier) {
|
||||||
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
|
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
|
||||||
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
|
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
|
||||||
|
|
||||||
if (isset($sourceClass->associationMappings[$field])) {
|
if (isset($sourceClass->associationMappings[$field])) {
|
||||||
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
||||||
$value = $value[$this->_em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]];
|
$value = $value[$this->_em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]];
|
||||||
}
|
}
|
||||||
|
|
||||||
$criteria[$quotedJoinTable . "." . $relationKeyColumn] = $value;
|
$criteria[$quotedJoinTable . "." . $relationKeyColumn] = $value;
|
||||||
} else if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
} else if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
||||||
$criteria[$quotedJoinTable . "." . $relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
$criteria[$quotedJoinTable . "." . $relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||||
@ -864,7 +864,7 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc, 0, $limit, $offset);
|
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc, 0, $limit, $offset);
|
||||||
list($params, $types) = $this->expandParameters($criteria);
|
list($params, $types) = $this->expandParameters($criteria);
|
||||||
|
|
||||||
return $this->_conn->executeQuery($sql, $params, $types);
|
return $this->_conn->executeQuery($sql, $params, $types);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -890,7 +890,7 @@ class BasicEntityPersister
|
|||||||
$orderBySql = $orderBy ? $this->_getOrderBySQL($orderBy, $this->_getSQLTableAlias($this->_class->name)) : '';
|
$orderBySql = $orderBy ? $this->_getOrderBySQL($orderBy, $this->_getSQLTableAlias($this->_class->name)) : '';
|
||||||
|
|
||||||
$lockSql = '';
|
$lockSql = '';
|
||||||
|
|
||||||
if ($lockMode == LockMode::PESSIMISTIC_READ) {
|
if ($lockMode == LockMode::PESSIMISTIC_READ) {
|
||||||
$lockSql = ' ' . $this->_platform->getReadLockSql();
|
$lockSql = ' ' . $this->_platform->getReadLockSql();
|
||||||
} else if ($lockMode == LockMode::PESSIMISTIC_WRITE) {
|
} else if ($lockMode == LockMode::PESSIMISTIC_WRITE) {
|
||||||
@ -908,7 +908,7 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the ORDER BY SQL snippet for ordered collections.
|
* Gets the ORDER BY SQL snippet for ordered collections.
|
||||||
*
|
*
|
||||||
* @param array $orderBy
|
* @param array $orderBy
|
||||||
* @param string $baseTableAlias
|
* @param string $baseTableAlias
|
||||||
* @return string
|
* @return string
|
||||||
@ -917,7 +917,7 @@ class BasicEntityPersister
|
|||||||
protected final function _getOrderBySQL(array $orderBy, $baseTableAlias)
|
protected final function _getOrderBySQL(array $orderBy, $baseTableAlias)
|
||||||
{
|
{
|
||||||
$orderBySql = '';
|
$orderBySql = '';
|
||||||
|
|
||||||
foreach ($orderBy as $fieldName => $orientation) {
|
foreach ($orderBy as $fieldName => $orientation) {
|
||||||
if ( ! isset($this->_class->fieldMappings[$fieldName])) {
|
if ( ! isset($this->_class->fieldMappings[$fieldName])) {
|
||||||
throw ORMException::unrecognizedField($fieldName);
|
throw ORMException::unrecognizedField($fieldName);
|
||||||
@ -928,7 +928,7 @@ class BasicEntityPersister
|
|||||||
: $baseTableAlias;
|
: $baseTableAlias;
|
||||||
|
|
||||||
$columnName = $this->_class->getQuotedColumnName($fieldName, $this->_platform);
|
$columnName = $this->_class->getQuotedColumnName($fieldName, $this->_platform);
|
||||||
|
|
||||||
$orderBySql .= $orderBySql ? ', ' : ' ORDER BY ';
|
$orderBySql .= $orderBySql ? ', ' : ' ORDER BY ';
|
||||||
$orderBySql .= $tableAlias . '.' . $columnName . ' ' . $orientation;
|
$orderBySql .= $tableAlias . '.' . $columnName . ' ' . $orientation;
|
||||||
}
|
}
|
||||||
@ -944,7 +944,7 @@ class BasicEntityPersister
|
|||||||
* list SQL fragment. Note that in the implementation of BasicEntityPersister
|
* list SQL fragment. Note that in the implementation of BasicEntityPersister
|
||||||
* the resulting SQL fragment is generated only once and cached in {@link _selectColumnListSql}.
|
* the resulting SQL fragment is generated only once and cached in {@link _selectColumnListSql}.
|
||||||
* Subclasses may or may not do the same.
|
* Subclasses may or may not do the same.
|
||||||
*
|
*
|
||||||
* @return string The SQL fragment.
|
* @return string The SQL fragment.
|
||||||
* @todo Rename: _getSelectColumnsSQL()
|
* @todo Rename: _getSelectColumnsSQL()
|
||||||
*/
|
*/
|
||||||
@ -961,75 +961,75 @@ class BasicEntityPersister
|
|||||||
// Add regular columns to select list
|
// Add regular columns to select list
|
||||||
foreach ($this->_class->fieldNames as $field) {
|
foreach ($this->_class->fieldNames as $field) {
|
||||||
if ($columnList) $columnList .= ', ';
|
if ($columnList) $columnList .= ', ';
|
||||||
|
|
||||||
$columnList .= $this->_getSelectColumnSQL($field, $this->_class);
|
$columnList .= $this->_getSelectColumnSQL($field, $this->_class);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_selectJoinSql = '';
|
$this->_selectJoinSql = '';
|
||||||
$eagerAliasCounter = 0;
|
$eagerAliasCounter = 0;
|
||||||
|
|
||||||
foreach ($this->_class->associationMappings as $assocField => $assoc) {
|
foreach ($this->_class->associationMappings as $assocField => $assoc) {
|
||||||
$assocColumnSQL = $this->_getSelectColumnAssociationSQL($assocField, $assoc, $this->_class);
|
$assocColumnSQL = $this->_getSelectColumnAssociationSQL($assocField, $assoc, $this->_class);
|
||||||
|
|
||||||
if ($assocColumnSQL) {
|
if ($assocColumnSQL) {
|
||||||
if ($columnList) $columnList .= ', ';
|
if ($columnList) $columnList .= ', ';
|
||||||
|
|
||||||
$columnList .= $assocColumnSQL;
|
$columnList .= $assocColumnSQL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($assoc['type'] & ClassMetadata::TO_ONE && ($assoc['fetch'] == ClassMetadata::FETCH_EAGER || !$assoc['isOwningSide'])) {
|
if ($assoc['type'] & ClassMetadata::TO_ONE && ($assoc['fetch'] == ClassMetadata::FETCH_EAGER || !$assoc['isOwningSide'])) {
|
||||||
$eagerEntity = $this->_em->getClassMetadata($assoc['targetEntity']);
|
$eagerEntity = $this->_em->getClassMetadata($assoc['targetEntity']);
|
||||||
|
|
||||||
if ($eagerEntity->inheritanceType != ClassMetadata::INHERITANCE_TYPE_NONE) {
|
if ($eagerEntity->inheritanceType != ClassMetadata::INHERITANCE_TYPE_NONE) {
|
||||||
continue; // now this is why you shouldn't use inheritance
|
continue; // now this is why you shouldn't use inheritance
|
||||||
}
|
}
|
||||||
|
|
||||||
$assocAlias = 'e' . ($eagerAliasCounter++);
|
$assocAlias = 'e' . ($eagerAliasCounter++);
|
||||||
$this->_rsm->addJoinedEntityResult($assoc['targetEntity'], $assocAlias, 'r', $assocField);
|
$this->_rsm->addJoinedEntityResult($assoc['targetEntity'], $assocAlias, 'r', $assocField);
|
||||||
|
|
||||||
foreach ($eagerEntity->fieldNames AS $field) {
|
foreach ($eagerEntity->fieldNames AS $field) {
|
||||||
if ($columnList) $columnList .= ', ';
|
if ($columnList) $columnList .= ', ';
|
||||||
|
|
||||||
$columnList .= $this->_getSelectColumnSQL($field, $eagerEntity, $assocAlias);
|
$columnList .= $this->_getSelectColumnSQL($field, $eagerEntity, $assocAlias);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($eagerEntity->associationMappings as $assoc2Field => $assoc2) {
|
foreach ($eagerEntity->associationMappings as $assoc2Field => $assoc2) {
|
||||||
$assoc2ColumnSQL = $this->_getSelectColumnAssociationSQL($assoc2Field, $assoc2, $eagerEntity, $assocAlias);
|
$assoc2ColumnSQL = $this->_getSelectColumnAssociationSQL($assoc2Field, $assoc2, $eagerEntity, $assocAlias);
|
||||||
|
|
||||||
if ($assoc2ColumnSQL) {
|
if ($assoc2ColumnSQL) {
|
||||||
if ($columnList) $columnList .= ', ';
|
if ($columnList) $columnList .= ', ';
|
||||||
$columnList .= $assoc2ColumnSQL;
|
$columnList .= $assoc2ColumnSQL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_selectJoinSql .= ' LEFT JOIN'; // TODO: Inner join when all join columns are NOT nullable.
|
$this->_selectJoinSql .= ' LEFT JOIN'; // TODO: Inner join when all join columns are NOT nullable.
|
||||||
$first = true;
|
$first = true;
|
||||||
|
|
||||||
if ($assoc['isOwningSide']) {
|
if ($assoc['isOwningSide']) {
|
||||||
$this->_selectJoinSql .= ' ' . $eagerEntity->getQuotedTableName($this->_platform) . ' ' . $this->_getSQLTableAlias($eagerEntity->name, $assocAlias) .' ON ';
|
$this->_selectJoinSql .= ' ' . $eagerEntity->getQuotedTableName($this->_platform) . ' ' . $this->_getSQLTableAlias($eagerEntity->name, $assocAlias) .' ON ';
|
||||||
|
|
||||||
foreach ($assoc['sourceToTargetKeyColumns'] AS $sourceCol => $targetCol) {
|
foreach ($assoc['sourceToTargetKeyColumns'] AS $sourceCol => $targetCol) {
|
||||||
if ( ! $first) {
|
if ( ! $first) {
|
||||||
$this->_selectJoinSql .= ' AND ';
|
$this->_selectJoinSql .= ' AND ';
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_selectJoinSql .= $this->_getSQLTableAlias($assoc['sourceEntity']) . '.' . $sourceCol . ' = '
|
$this->_selectJoinSql .= $this->_getSQLTableAlias($assoc['sourceEntity']) . '.' . $sourceCol . ' = '
|
||||||
. $this->_getSQLTableAlias($assoc['targetEntity'], $assocAlias) . '.' . $targetCol . ' ';
|
. $this->_getSQLTableAlias($assoc['targetEntity'], $assocAlias) . '.' . $targetCol . ' ';
|
||||||
$first = false;
|
$first = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$eagerEntity = $this->_em->getClassMetadata($assoc['targetEntity']);
|
$eagerEntity = $this->_em->getClassMetadata($assoc['targetEntity']);
|
||||||
$owningAssoc = $eagerEntity->getAssociationMapping($assoc['mappedBy']);
|
$owningAssoc = $eagerEntity->getAssociationMapping($assoc['mappedBy']);
|
||||||
|
|
||||||
$this->_selectJoinSql .= ' ' . $eagerEntity->getQuotedTableName($this->_platform) . ' '
|
$this->_selectJoinSql .= ' ' . $eagerEntity->getQuotedTableName($this->_platform) . ' '
|
||||||
. $this->_getSQLTableAlias($eagerEntity->name, $assocAlias) . ' ON ';
|
. $this->_getSQLTableAlias($eagerEntity->name, $assocAlias) . ' ON ';
|
||||||
|
|
||||||
foreach ($owningAssoc['sourceToTargetKeyColumns'] AS $sourceCol => $targetCol) {
|
foreach ($owningAssoc['sourceToTargetKeyColumns'] AS $sourceCol => $targetCol) {
|
||||||
if ( ! $first) {
|
if ( ! $first) {
|
||||||
$this->_selectJoinSql .= ' AND ';
|
$this->_selectJoinSql .= ' AND ';
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_selectJoinSql .= $this->_getSQLTableAlias($owningAssoc['sourceEntity'], $assocAlias) . '.' . $sourceCol . ' = '
|
$this->_selectJoinSql .= $this->_getSQLTableAlias($owningAssoc['sourceEntity'], $assocAlias) . '.' . $sourceCol . ' = '
|
||||||
. $this->_getSQLTableAlias($owningAssoc['targetEntity']) . '.' . $targetCol . ' ';
|
. $this->_getSQLTableAlias($owningAssoc['targetEntity']) . '.' . $targetCol . ' ';
|
||||||
$first = false;
|
$first = false;
|
||||||
}
|
}
|
||||||
@ -1041,33 +1041,33 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
return $this->_selectColumnListSql;
|
return $this->_selectColumnListSql;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the SQL join fragment used when selecting entities from an association.
|
* Gets the SQL join fragment used when selecting entities from an association.
|
||||||
*
|
*
|
||||||
* @param string $field
|
* @param string $field
|
||||||
* @param array $assoc
|
* @param array $assoc
|
||||||
* @param ClassMetadata $class
|
* @param ClassMetadata $class
|
||||||
* @param string $alias
|
* @param string $alias
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function _getSelectColumnAssociationSQL($field, $assoc, ClassMetadata $class, $alias = 'r')
|
protected function _getSelectColumnAssociationSQL($field, $assoc, ClassMetadata $class, $alias = 'r')
|
||||||
{
|
{
|
||||||
$columnList = '';
|
$columnList = '';
|
||||||
|
|
||||||
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
|
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
|
||||||
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
|
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
|
||||||
if ($columnList) $columnList .= ', ';
|
if ($columnList) $columnList .= ', ';
|
||||||
|
|
||||||
$columnAlias = $srcColumn . $this->_sqlAliasCounter++;
|
$columnAlias = $srcColumn . $this->_sqlAliasCounter++;
|
||||||
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
|
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
|
||||||
$columnList .= $this->_getSQLTableAlias($class->name, ($alias == 'r' ? '' : $alias) )
|
$columnList .= $this->_getSQLTableAlias($class->name, ($alias == 'r' ? '' : $alias) )
|
||||||
. '.' . $srcColumn . ' AS ' . $resultColumnName;
|
. '.' . $srcColumn . ' AS ' . $resultColumnName;
|
||||||
$this->_rsm->addMetaResult($alias, $resultColumnName, $srcColumn, isset($assoc['id']) && $assoc['id'] === true);
|
$this->_rsm->addMetaResult($alias, $resultColumnName, $srcColumn, isset($assoc['id']) && $assoc['id'] === true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $columnList;
|
return $columnList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1087,10 +1087,10 @@ class BasicEntityPersister
|
|||||||
$owningAssoc = $this->_em->getClassMetadata($manyToMany['targetEntity'])->associationMappings[$manyToMany['mappedBy']];
|
$owningAssoc = $this->_em->getClassMetadata($manyToMany['targetEntity'])->associationMappings[$manyToMany['mappedBy']];
|
||||||
$joinClauses = $owningAssoc['relationToSourceKeyColumns'];
|
$joinClauses = $owningAssoc['relationToSourceKeyColumns'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$joinTableName = $this->_class->getQuotedJoinTableName($owningAssoc, $this->_platform);
|
$joinTableName = $this->_class->getQuotedJoinTableName($owningAssoc, $this->_platform);
|
||||||
$joinSql = '';
|
$joinSql = '';
|
||||||
|
|
||||||
foreach ($joinClauses as $joinTableColumn => $sourceColumn) {
|
foreach ($joinClauses as $joinTableColumn => $sourceColumn) {
|
||||||
if ($joinSql != '') $joinSql .= ' AND ';
|
if ($joinSql != '') $joinSql .= ' AND ';
|
||||||
|
|
||||||
@ -1109,7 +1109,7 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the INSERT SQL used by the persister to persist a new entity.
|
* Gets the INSERT SQL used by the persister to persist a new entity.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function _getInsertSQL()
|
protected function _getInsertSQL()
|
||||||
@ -1117,7 +1117,7 @@ class BasicEntityPersister
|
|||||||
if ($this->_insertSql === null) {
|
if ($this->_insertSql === null) {
|
||||||
$insertSql = '';
|
$insertSql = '';
|
||||||
$columns = $this->_getInsertColumnList();
|
$columns = $this->_getInsertColumnList();
|
||||||
|
|
||||||
if (empty($columns)) {
|
if (empty($columns)) {
|
||||||
$insertSql = $this->_platform->getEmptyIdentityInsertSQL(
|
$insertSql = $this->_platform->getEmptyIdentityInsertSQL(
|
||||||
$this->_class->getQuotedTableName($this->_platform),
|
$this->_class->getQuotedTableName($this->_platform),
|
||||||
@ -1130,10 +1130,10 @@ class BasicEntityPersister
|
|||||||
$insertSql = 'INSERT INTO ' . $this->_class->getQuotedTableName($this->_platform)
|
$insertSql = 'INSERT INTO ' . $this->_class->getQuotedTableName($this->_platform)
|
||||||
. ' (' . implode(', ', $columns) . ') VALUES (' . implode(', ', $values) . ')';
|
. ' (' . implode(', ', $columns) . ') VALUES (' . implode(', ', $values) . ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_insertSql = $insertSql;
|
$this->_insertSql = $insertSql;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->_insertSql;
|
return $this->_insertSql;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1148,15 +1148,15 @@ class BasicEntityPersister
|
|||||||
protected function _getInsertColumnList()
|
protected function _getInsertColumnList()
|
||||||
{
|
{
|
||||||
$columns = array();
|
$columns = array();
|
||||||
|
|
||||||
foreach ($this->_class->reflFields as $name => $field) {
|
foreach ($this->_class->reflFields as $name => $field) {
|
||||||
if ($this->_class->isVersioned && $this->_class->versionField == $name) {
|
if ($this->_class->isVersioned && $this->_class->versionField == $name) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->_class->associationMappings[$name])) {
|
if (isset($this->_class->associationMappings[$name])) {
|
||||||
$assoc = $this->_class->associationMappings[$name];
|
$assoc = $this->_class->associationMappings[$name];
|
||||||
|
|
||||||
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
|
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
|
||||||
foreach ($assoc['targetToSourceKeyColumns'] as $sourceCol) {
|
foreach ($assoc['targetToSourceKeyColumns'] as $sourceCol) {
|
||||||
$columns[] = $sourceCol;
|
$columns[] = $sourceCol;
|
||||||
@ -1181,10 +1181,10 @@ class BasicEntityPersister
|
|||||||
protected function _getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r')
|
protected function _getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r')
|
||||||
{
|
{
|
||||||
$columnName = $class->columnNames[$field];
|
$columnName = $class->columnNames[$field];
|
||||||
$sql = $this->_getSQLTableAlias($class->name, $alias == 'r' ? '' : $alias)
|
$sql = $this->_getSQLTableAlias($class->name, $alias == 'r' ? '' : $alias)
|
||||||
. '.' . $class->getQuotedColumnName($field, $this->_platform);
|
. '.' . $class->getQuotedColumnName($field, $this->_platform);
|
||||||
$columnAlias = $this->_platform->getSQLResultCasing($columnName . $this->_sqlAliasCounter++);
|
$columnAlias = $this->_platform->getSQLResultCasing($columnName . $this->_sqlAliasCounter++);
|
||||||
|
|
||||||
$this->_rsm->addFieldResult($alias, $columnAlias, $field);
|
$this->_rsm->addFieldResult($alias, $columnAlias, $field);
|
||||||
|
|
||||||
return $sql . ' AS ' . $columnAlias;
|
return $sql . ' AS ' . $columnAlias;
|
||||||
@ -1192,7 +1192,7 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the SQL table alias for the given class name.
|
* Gets the SQL table alias for the given class name.
|
||||||
*
|
*
|
||||||
* @param string $className
|
* @param string $className
|
||||||
* @return string The SQL table alias.
|
* @return string The SQL table alias.
|
||||||
* @todo Reconsider. Binding table aliases to class names is not such a good idea.
|
* @todo Reconsider. Binding table aliases to class names is not such a good idea.
|
||||||
@ -1202,15 +1202,15 @@ class BasicEntityPersister
|
|||||||
if ($assocName) {
|
if ($assocName) {
|
||||||
$className .= '#' . $assocName;
|
$className .= '#' . $assocName;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->_sqlTableAliases[$className])) {
|
if (isset($this->_sqlTableAliases[$className])) {
|
||||||
return $this->_sqlTableAliases[$className];
|
return $this->_sqlTableAliases[$className];
|
||||||
}
|
}
|
||||||
|
|
||||||
$tableAlias = 't' . $this->_sqlAliasCounter++;
|
$tableAlias = 't' . $this->_sqlAliasCounter++;
|
||||||
|
|
||||||
$this->_sqlTableAliases[$className] = $tableAlias;
|
$this->_sqlTableAliases[$className] = $tableAlias;
|
||||||
|
|
||||||
return $tableAlias;
|
return $tableAlias;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1234,9 +1234,9 @@ class BasicEntityPersister
|
|||||||
$sql = 'SELECT 1 '
|
$sql = 'SELECT 1 '
|
||||||
. $this->_platform->appendLockHint($this->getLockTablesSql(), $lockMode)
|
. $this->_platform->appendLockHint($this->getLockTablesSql(), $lockMode)
|
||||||
. ($conditionSql ? ' WHERE ' . $conditionSql : '') . ' ' . $lockSql;
|
. ($conditionSql ? ' WHERE ' . $conditionSql : '') . ' ' . $lockSql;
|
||||||
|
|
||||||
list($params, $types) = $this->expandParameters($criteria);
|
list($params, $types) = $this->expandParameters($criteria);
|
||||||
|
|
||||||
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1265,25 +1265,25 @@ class BasicEntityPersister
|
|||||||
protected function _getSelectConditionSQL(array $criteria, $assoc = null)
|
protected function _getSelectConditionSQL(array $criteria, $assoc = null)
|
||||||
{
|
{
|
||||||
$conditionSql = '';
|
$conditionSql = '';
|
||||||
|
|
||||||
foreach ($criteria as $field => $value) {
|
foreach ($criteria as $field => $value) {
|
||||||
$conditionSql .= $conditionSql ? ' AND ' : '';
|
$conditionSql .= $conditionSql ? ' AND ' : '';
|
||||||
|
|
||||||
if (isset($this->_class->columnNames[$field])) {
|
if (isset($this->_class->columnNames[$field])) {
|
||||||
$className = (isset($this->_class->fieldMappings[$field]['inherited']))
|
$className = (isset($this->_class->fieldMappings[$field]['inherited']))
|
||||||
? $this->_class->fieldMappings[$field]['inherited']
|
? $this->_class->fieldMappings[$field]['inherited']
|
||||||
: $this->_class->name;
|
: $this->_class->name;
|
||||||
|
|
||||||
$conditionSql .= $this->_getSQLTableAlias($className) . '.' . $this->_class->getQuotedColumnName($field, $this->_platform);
|
$conditionSql .= $this->_getSQLTableAlias($className) . '.' . $this->_class->getQuotedColumnName($field, $this->_platform);
|
||||||
} else if (isset($this->_class->associationMappings[$field])) {
|
} else if (isset($this->_class->associationMappings[$field])) {
|
||||||
if ( ! $this->_class->associationMappings[$field]['isOwningSide']) {
|
if ( ! $this->_class->associationMappings[$field]['isOwningSide']) {
|
||||||
throw ORMException::invalidFindByInverseAssociation($this->_class->name, $field);
|
throw ORMException::invalidFindByInverseAssociation($this->_class->name, $field);
|
||||||
}
|
}
|
||||||
|
|
||||||
$className = (isset($this->_class->associationMappings[$field]['inherited']))
|
$className = (isset($this->_class->associationMappings[$field]['inherited']))
|
||||||
? $this->_class->associationMappings[$field]['inherited']
|
? $this->_class->associationMappings[$field]['inherited']
|
||||||
: $this->_class->name;
|
: $this->_class->name;
|
||||||
|
|
||||||
$conditionSql .= $this->_getSQLTableAlias($className) . '.' . $this->_class->associationMappings[$field]['joinColumns'][0]['name'];
|
$conditionSql .= $this->_getSQLTableAlias($className) . '.' . $this->_class->associationMappings[$field]['joinColumns'][0]['name'];
|
||||||
} else if ($assoc !== null && strpos($field, " ") === false && strpos($field, "(") === false) {
|
} else if ($assoc !== null && strpos($field, " ") === false && strpos($field, "(") === false) {
|
||||||
// very careless developers could potentially open up this normally hidden api for userland attacks,
|
// very careless developers could potentially open up this normally hidden api for userland attacks,
|
||||||
@ -1294,7 +1294,7 @@ class BasicEntityPersister
|
|||||||
} else {
|
} else {
|
||||||
throw ORMException::unrecognizedField($field);
|
throw ORMException::unrecognizedField($field);
|
||||||
}
|
}
|
||||||
|
|
||||||
$conditionSql .= (is_array($value)) ? ' IN (?)' : (($value === null) ? ' IS NULL' : ' = ?');
|
$conditionSql .= (is_array($value)) ? ' IN (?)' : (($value === null) ? ' IS NULL' : ' = ?');
|
||||||
}
|
}
|
||||||
return $conditionSql;
|
return $conditionSql;
|
||||||
@ -1312,7 +1312,7 @@ class BasicEntityPersister
|
|||||||
public function getOneToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null)
|
public function getOneToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null)
|
||||||
{
|
{
|
||||||
$stmt = $this->getOneToManyStatement($assoc, $sourceEntity, $offset, $limit);
|
$stmt = $this->getOneToManyStatement($assoc, $sourceEntity, $offset, $limit);
|
||||||
|
|
||||||
return $this->loadArrayFromStatement($assoc, $stmt);
|
return $this->loadArrayFromStatement($assoc, $stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1328,7 +1328,7 @@ class BasicEntityPersister
|
|||||||
public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
|
public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
|
||||||
{
|
{
|
||||||
$stmt = $this->getOneToManyStatement($assoc, $sourceEntity);
|
$stmt = $this->getOneToManyStatement($assoc, $sourceEntity);
|
||||||
|
|
||||||
return $this->loadCollectionFromStatement($assoc, $stmt, $coll);
|
return $this->loadCollectionFromStatement($assoc, $stmt, $coll);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1353,12 +1353,12 @@ class BasicEntityPersister
|
|||||||
if ($sourceClass->containsForeignIdentifier) {
|
if ($sourceClass->containsForeignIdentifier) {
|
||||||
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
|
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
|
||||||
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
|
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
|
||||||
|
|
||||||
if (isset($sourceClass->associationMappings[$field])) {
|
if (isset($sourceClass->associationMappings[$field])) {
|
||||||
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
||||||
$value = $value[$this->_em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]];
|
$value = $value[$this->_em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]];
|
||||||
}
|
}
|
||||||
|
|
||||||
$criteria[$tableAlias . "." . $targetKeyColumn] = $value;
|
$criteria[$tableAlias . "." . $targetKeyColumn] = $value;
|
||||||
} else {
|
} else {
|
||||||
$criteria[$tableAlias . "." . $targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
$criteria[$tableAlias . "." . $targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||||
@ -1389,13 +1389,13 @@ class BasicEntityPersister
|
|||||||
$types[] = $this->getType($field, $value);
|
$types[] = $this->getType($field, $value);
|
||||||
$params[] = $this->getValue($value);
|
$params[] = $this->getValue($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return array($params, $types);
|
return array($params, $types);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Infer field type to be used by parameter type casting.
|
* Infer field type to be used by parameter type casting.
|
||||||
*
|
*
|
||||||
* @param string $field
|
* @param string $field
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
* @return integer
|
* @return integer
|
||||||
@ -1409,11 +1409,11 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
case (isset($this->_class->associationMappings[$field])):
|
case (isset($this->_class->associationMappings[$field])):
|
||||||
$assoc = $this->_class->associationMappings[$field];
|
$assoc = $this->_class->associationMappings[$field];
|
||||||
|
|
||||||
if (count($assoc['sourceToTargetKeyColumns']) > 1) {
|
if (count($assoc['sourceToTargetKeyColumns']) > 1) {
|
||||||
throw Query\QueryException::associationPathCompositeKeyNotSupported();
|
throw Query\QueryException::associationPathCompositeKeyNotSupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
$targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
|
$targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
|
||||||
$targetColumn = $assoc['joinColumns'][0]['referencedColumnName'];
|
$targetColumn = $assoc['joinColumns'][0]['referencedColumnName'];
|
||||||
$type = null;
|
$type = null;
|
||||||
@ -1431,36 +1431,36 @@ class BasicEntityPersister
|
|||||||
if (is_array($value)) {
|
if (is_array($value)) {
|
||||||
$type += Connection::ARRAY_PARAM_OFFSET;
|
$type += Connection::ARRAY_PARAM_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $type;
|
return $type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve parameter value
|
* Retrieve parameter value
|
||||||
*
|
*
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
private function getValue($value)
|
private function getValue($value)
|
||||||
{
|
{
|
||||||
if (is_array($value)) {
|
if (is_array($value)) {
|
||||||
$newValue = array();
|
$newValue = array();
|
||||||
|
|
||||||
foreach ($value as $itemValue) {
|
foreach ($value as $itemValue) {
|
||||||
$newValue[] = $this->getIndividualValue($itemValue);
|
$newValue[] = $this->getIndividualValue($itemValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $newValue;
|
return $newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->getIndividualValue($value);
|
return $this->getIndividualValue($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve an invidiual parameter value
|
* Retrieve an invidiual parameter value
|
||||||
*
|
*
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
private function getIndividualValue($value)
|
private function getIndividualValue($value)
|
||||||
{
|
{
|
||||||
@ -1471,11 +1471,11 @@ class BasicEntityPersister
|
|||||||
$class = $this->_em->getClassMetadata(get_class($value));
|
$class = $this->_em->getClassMetadata(get_class($value));
|
||||||
$idValues = $class->getIdentifierValues($value);
|
$idValues = $class->getIdentifierValues($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = $idValues[key($idValues)];
|
$value = $idValues[key($idValues)];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1487,17 +1487,17 @@ class BasicEntityPersister
|
|||||||
public function exists($entity, array $extraConditions = array())
|
public function exists($entity, array $extraConditions = array())
|
||||||
{
|
{
|
||||||
$criteria = $this->_class->getIdentifierValues($entity);
|
$criteria = $this->_class->getIdentifierValues($entity);
|
||||||
|
|
||||||
if ($extraConditions) {
|
if ($extraConditions) {
|
||||||
$criteria = array_merge($criteria, $extraConditions);
|
$criteria = array_merge($criteria, $extraConditions);
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql = 'SELECT 1'
|
$sql = 'SELECT 1 '
|
||||||
. ' FROM ' . $this->_class->getQuotedTableName($this->_platform) . ' ' . $this->_getSQLTableAlias($this->_class->name)
|
. $this->getLockTablesSql()
|
||||||
. ' WHERE ' . $this->_getSelectConditionSQL($criteria);
|
. ' WHERE ' . $this->_getSelectConditionSQL($criteria);
|
||||||
|
|
||||||
list($params, $types) = $this->expandParameters($criteria);
|
list($params, $types) = $this->expandParameters($criteria);
|
||||||
|
|
||||||
return (bool) $this->_conn->fetchColumn($sql, $params);
|
return (bool) $this->_conn->fetchColumn($sql, $params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Map of table to quoted table names.
|
* Map of table to quoted table names.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private $_quotedTableMap = array();
|
private $_quotedTableMap = array();
|
||||||
@ -59,7 +59,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
$class = ($this->_class->name !== $this->_class->rootEntityName)
|
$class = ($this->_class->name !== $this->_class->rootEntityName)
|
||||||
? $this->_em->getClassMetadata($this->_class->rootEntityName)
|
? $this->_em->getClassMetadata($this->_class->rootEntityName)
|
||||||
: $this->_class;
|
: $this->_class;
|
||||||
|
|
||||||
return $class->getTableName();
|
return $class->getTableName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,10 +73,10 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
{
|
{
|
||||||
if (isset($this->_class->fieldMappings[$this->_class->versionField]['inherited'])) {
|
if (isset($this->_class->fieldMappings[$this->_class->versionField]['inherited'])) {
|
||||||
$definingClassName = $this->_class->fieldMappings[$this->_class->versionField]['inherited'];
|
$definingClassName = $this->_class->fieldMappings[$this->_class->versionField]['inherited'];
|
||||||
|
|
||||||
return $this->_em->getClassMetadata($definingClassName);
|
return $this->_em->getClassMetadata($definingClassName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->_class;
|
return $this->_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
if (isset($this->_owningTableMap[$fieldName])) {
|
if (isset($this->_owningTableMap[$fieldName])) {
|
||||||
return $this->_owningTableMap[$fieldName];
|
return $this->_owningTableMap[$fieldName];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->_class->associationMappings[$fieldName]['inherited'])) {
|
if (isset($this->_class->associationMappings[$fieldName]['inherited'])) {
|
||||||
$cm = $this->_em->getClassMetadata($this->_class->associationMappings[$fieldName]['inherited']);
|
$cm = $this->_em->getClassMetadata($this->_class->associationMappings[$fieldName]['inherited']);
|
||||||
} else if (isset($this->_class->fieldMappings[$fieldName]['inherited'])) {
|
} else if (isset($this->_class->fieldMappings[$fieldName]['inherited'])) {
|
||||||
@ -130,15 +130,15 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
|
|
||||||
// Prepare statements for sub tables.
|
// Prepare statements for sub tables.
|
||||||
$subTableStmts = array();
|
$subTableStmts = array();
|
||||||
|
|
||||||
if ($rootClass !== $this->_class) {
|
if ($rootClass !== $this->_class) {
|
||||||
$subTableStmts[$this->_class->getTableName()] = $this->_conn->prepare($this->_getInsertSQL());
|
$subTableStmts[$this->_class->getTableName()] = $this->_conn->prepare($this->_getInsertSQL());
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->_class->parentClasses as $parentClassName) {
|
foreach ($this->_class->parentClasses as $parentClassName) {
|
||||||
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
||||||
$parentTableName = $parentClass->getTableName();
|
$parentTableName = $parentClass->getTableName();
|
||||||
|
|
||||||
if ($parentClass !== $rootClass) {
|
if ($parentClass !== $rootClass) {
|
||||||
$parentPersister = $this->_em->getUnitOfWork()->getEntityPersister($parentClassName);
|
$parentPersister = $this->_em->getUnitOfWork()->getEntityPersister($parentClassName);
|
||||||
$subTableStmts[$parentTableName] = $this->_conn->prepare($parentPersister->_getInsertSQL());
|
$subTableStmts[$parentTableName] = $this->_conn->prepare($parentPersister->_getInsertSQL());
|
||||||
@ -153,11 +153,11 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
|
|
||||||
// Execute insert on root table
|
// Execute insert on root table
|
||||||
$paramIndex = 1;
|
$paramIndex = 1;
|
||||||
|
|
||||||
foreach ($insertData[$rootTableName] as $columnName => $value) {
|
foreach ($insertData[$rootTableName] as $columnName => $value) {
|
||||||
$rootTableStmt->bindValue($paramIndex++, $value, $this->_columnTypes[$columnName]);
|
$rootTableStmt->bindValue($paramIndex++, $value, $this->_columnTypes[$columnName]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$rootTableStmt->execute();
|
$rootTableStmt->execute();
|
||||||
|
|
||||||
if ($isPostInsertId) {
|
if ($isPostInsertId) {
|
||||||
@ -172,23 +172,23 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
foreach ($subTableStmts as $tableName => $stmt) {
|
foreach ($subTableStmts as $tableName => $stmt) {
|
||||||
$data = isset($insertData[$tableName]) ? $insertData[$tableName] : array();
|
$data = isset($insertData[$tableName]) ? $insertData[$tableName] : array();
|
||||||
$paramIndex = 1;
|
$paramIndex = 1;
|
||||||
|
|
||||||
foreach ((array) $id as $idName => $idVal) {
|
foreach ((array) $id as $idName => $idVal) {
|
||||||
$type = isset($this->_columnTypes[$idName]) ? $this->_columnTypes[$idName] : Type::STRING;
|
$type = isset($this->_columnTypes[$idName]) ? $this->_columnTypes[$idName] : Type::STRING;
|
||||||
|
|
||||||
$stmt->bindValue($paramIndex++, $idVal, $type);
|
$stmt->bindValue($paramIndex++, $idVal, $type);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($data as $columnName => $value) {
|
foreach ($data as $columnName => $value) {
|
||||||
$stmt->bindValue($paramIndex++, $value, $this->_columnTypes[$columnName]);
|
$stmt->bindValue($paramIndex++, $value, $this->_columnTypes[$columnName]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$rootTableStmt->closeCursor();
|
$rootTableStmt->closeCursor();
|
||||||
|
|
||||||
foreach ($subTableStmts as $stmt) {
|
foreach ($subTableStmts as $stmt) {
|
||||||
$stmt->closeCursor();
|
$stmt->closeCursor();
|
||||||
}
|
}
|
||||||
@ -220,7 +220,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
$entity, $this->_quotedTableMap[$tableName], $data, $isVersioned && $versionedTable == $tableName
|
$entity, $this->_quotedTableMap[$tableName], $data, $isVersioned && $versionedTable == $tableName
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the table with the version column is updated even if no columns on that
|
// Make sure the table with the version column is updated even if no columns on that
|
||||||
// table were affected.
|
// table were affected.
|
||||||
if ($isVersioned && ! isset($updateData[$versionedTable])) {
|
if ($isVersioned && ! isset($updateData[$versionedTable])) {
|
||||||
@ -251,7 +251,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
} else {
|
} else {
|
||||||
// Delete from all tables individually, starting from this class' table up to the root table.
|
// Delete from all tables individually, starting from this class' table up to the root table.
|
||||||
$this->_conn->delete($this->_class->getQuotedTableName($this->_platform), $id);
|
$this->_conn->delete($this->_class->getQuotedTableName($this->_platform), $id);
|
||||||
|
|
||||||
foreach ($this->_class->parentClasses as $parentClass) {
|
foreach ($this->_class->parentClasses as $parentClass) {
|
||||||
$this->_conn->delete(
|
$this->_conn->delete(
|
||||||
$this->_em->getClassMetadata($parentClass)->getQuotedTableName($this->_platform), $id
|
$this->_em->getClassMetadata($parentClass)->getQuotedTableName($this->_platform), $id
|
||||||
@ -270,16 +270,16 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
|
|
||||||
// Create the column list fragment only once
|
// Create the column list fragment only once
|
||||||
if ($this->_selectColumnListSql === null) {
|
if ($this->_selectColumnListSql === null) {
|
||||||
|
|
||||||
$this->_rsm = new ResultSetMapping();
|
$this->_rsm = new ResultSetMapping();
|
||||||
$this->_rsm->addEntityResult($this->_class->name, 'r');
|
$this->_rsm->addEntityResult($this->_class->name, 'r');
|
||||||
|
|
||||||
// Add regular columns
|
// Add regular columns
|
||||||
$columnList = '';
|
$columnList = '';
|
||||||
|
|
||||||
foreach ($this->_class->fieldMappings as $fieldName => $mapping) {
|
foreach ($this->_class->fieldMappings as $fieldName => $mapping) {
|
||||||
if ($columnList != '') $columnList .= ', ';
|
if ($columnList != '') $columnList .= ', ';
|
||||||
|
|
||||||
$columnList .= $this->_getSelectColumnSQL(
|
$columnList .= $this->_getSelectColumnSQL(
|
||||||
$fieldName,
|
$fieldName,
|
||||||
isset($mapping['inherited']) ? $this->_em->getClassMetadata($mapping['inherited']) : $this->_class
|
isset($mapping['inherited']) ? $this->_em->getClassMetadata($mapping['inherited']) : $this->_class
|
||||||
@ -290,12 +290,12 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
foreach ($this->_class->associationMappings as $assoc2) {
|
foreach ($this->_class->associationMappings as $assoc2) {
|
||||||
if ($assoc2['isOwningSide'] && $assoc2['type'] & ClassMetadata::TO_ONE) {
|
if ($assoc2['isOwningSide'] && $assoc2['type'] & ClassMetadata::TO_ONE) {
|
||||||
$tableAlias = isset($assoc2['inherited']) ? $this->_getSQLTableAlias($assoc2['inherited']) : $baseTableAlias;
|
$tableAlias = isset($assoc2['inherited']) ? $this->_getSQLTableAlias($assoc2['inherited']) : $baseTableAlias;
|
||||||
|
|
||||||
foreach ($assoc2['targetToSourceKeyColumns'] as $srcColumn) {
|
foreach ($assoc2['targetToSourceKeyColumns'] as $srcColumn) {
|
||||||
if ($columnList != '') $columnList .= ', ';
|
if ($columnList != '') $columnList .= ', ';
|
||||||
|
|
||||||
$columnList .= $this->getSelectJoinColumnSQL(
|
$columnList .= $this->getSelectJoinColumnSQL(
|
||||||
$tableAlias,
|
$tableAlias,
|
||||||
$srcColumn,
|
$srcColumn,
|
||||||
isset($assoc2['inherited']) ? $assoc2['inherited'] : $this->_class->name
|
isset($assoc2['inherited']) ? $assoc2['inherited'] : $this->_class->name
|
||||||
);
|
);
|
||||||
@ -309,23 +309,23 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
$columnList .= ', ' . $tableAlias . '.' . $discrColumn;
|
$columnList .= ', ' . $tableAlias . '.' . $discrColumn;
|
||||||
|
|
||||||
$resultColumnName = $this->_platform->getSQLResultCasing($discrColumn);
|
$resultColumnName = $this->_platform->getSQLResultCasing($discrColumn);
|
||||||
|
|
||||||
$this->_rsm->setDiscriminatorColumn('r', $resultColumnName);
|
$this->_rsm->setDiscriminatorColumn('r', $resultColumnName);
|
||||||
$this->_rsm->addMetaResult('r', $resultColumnName, $discrColumn);
|
$this->_rsm->addMetaResult('r', $resultColumnName, $discrColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
// INNER JOIN parent tables
|
// INNER JOIN parent tables
|
||||||
$joinSql = '';
|
$joinSql = '';
|
||||||
|
|
||||||
foreach ($this->_class->parentClasses as $parentClassName) {
|
foreach ($this->_class->parentClasses as $parentClassName) {
|
||||||
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
||||||
$tableAlias = $this->_getSQLTableAlias($parentClassName);
|
$tableAlias = $this->_getSQLTableAlias($parentClassName);
|
||||||
$joinSql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
|
$joinSql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
|
||||||
$first = true;
|
$first = true;
|
||||||
|
|
||||||
foreach ($idColumns as $idColumn) {
|
foreach ($idColumns as $idColumn) {
|
||||||
if ($first) $first = false; else $joinSql .= ' AND ';
|
if ($first) $first = false; else $joinSql .= ' AND ';
|
||||||
|
|
||||||
$joinSql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
|
$joinSql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -339,7 +339,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
// Add subclass columns
|
// Add subclass columns
|
||||||
foreach ($subClass->fieldMappings as $fieldName => $mapping) {
|
foreach ($subClass->fieldMappings as $fieldName => $mapping) {
|
||||||
if (isset($mapping['inherited'])) continue;
|
if (isset($mapping['inherited'])) continue;
|
||||||
|
|
||||||
$columnList .= ', ' . $this->_getSelectColumnSQL($fieldName, $subClass);
|
$columnList .= ', ' . $this->_getSelectColumnSQL($fieldName, $subClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,9 +348,9 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
if ($assoc2['isOwningSide'] && $assoc2['type'] & ClassMetadata::TO_ONE && ! isset($assoc2['inherited'])) {
|
if ($assoc2['isOwningSide'] && $assoc2['type'] & ClassMetadata::TO_ONE && ! isset($assoc2['inherited'])) {
|
||||||
foreach ($assoc2['targetToSourceKeyColumns'] as $srcColumn) {
|
foreach ($assoc2['targetToSourceKeyColumns'] as $srcColumn) {
|
||||||
if ($columnList != '') $columnList .= ', ';
|
if ($columnList != '') $columnList .= ', ';
|
||||||
|
|
||||||
$columnList .= $this->getSelectJoinColumnSQL(
|
$columnList .= $this->getSelectJoinColumnSQL(
|
||||||
$tableAlias,
|
$tableAlias,
|
||||||
$srcColumn,
|
$srcColumn,
|
||||||
isset($assoc2['inherited']) ? $assoc2['inherited'] : $subClass->name
|
isset($assoc2['inherited']) ? $assoc2['inherited'] : $subClass->name
|
||||||
);
|
);
|
||||||
@ -362,10 +362,10 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
// Add LEFT JOIN
|
// Add LEFT JOIN
|
||||||
$joinSql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
|
$joinSql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
|
||||||
$first = true;
|
$first = true;
|
||||||
|
|
||||||
foreach ($idColumns as $idColumn) {
|
foreach ($idColumns as $idColumn) {
|
||||||
if ($first) $first = false; else $joinSql .= ' AND ';
|
if ($first) $first = false; else $joinSql .= ' AND ';
|
||||||
|
|
||||||
$joinSql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
|
$joinSql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -382,7 +382,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
}
|
}
|
||||||
|
|
||||||
$lockSql = '';
|
$lockSql = '';
|
||||||
|
|
||||||
if ($lockMode == LockMode::PESSIMISTIC_READ) {
|
if ($lockMode == LockMode::PESSIMISTIC_READ) {
|
||||||
$lockSql = ' ' . $this->_platform->getReadLockSql();
|
$lockSql = ' ' . $this->_platform->getReadLockSql();
|
||||||
} else if ($lockMode == LockMode::PESSIMISTIC_WRITE) {
|
} else if ($lockMode == LockMode::PESSIMISTIC_WRITE) {
|
||||||
@ -408,29 +408,29 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
|
|
||||||
// INNER JOIN parent tables
|
// INNER JOIN parent tables
|
||||||
$joinSql = '';
|
$joinSql = '';
|
||||||
|
|
||||||
foreach ($this->_class->parentClasses as $parentClassName) {
|
foreach ($this->_class->parentClasses as $parentClassName) {
|
||||||
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
||||||
$tableAlias = $this->_getSQLTableAlias($parentClassName);
|
$tableAlias = $this->_getSQLTableAlias($parentClassName);
|
||||||
$joinSql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
|
$joinSql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
|
||||||
$first = true;
|
$first = true;
|
||||||
|
|
||||||
foreach ($idColumns as $idColumn) {
|
foreach ($idColumns as $idColumn) {
|
||||||
if ($first) $first = false; else $joinSql .= ' AND ';
|
if ($first) $first = false; else $joinSql .= ' AND ';
|
||||||
|
|
||||||
$joinSql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
|
$joinSql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'FROM ' . $this->_class->getQuotedTableName($this->_platform) . ' ' . $baseTableAlias . $joinSql;
|
return 'FROM ' . $this->_class->getQuotedTableName($this->_platform) . ' ' . $baseTableAlias . $joinSql;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure this method is never called. This persister overrides _getSelectEntitiesSQL directly. */
|
/* Ensure this method is never called. This persister overrides _getSelectEntitiesSQL directly. */
|
||||||
protected function _getSelectColumnListSQL()
|
protected function _getSelectColumnListSQL()
|
||||||
{
|
{
|
||||||
throw new \BadMethodCallException("Illegal invocation of ".__METHOD__.".");
|
throw new \BadMethodCallException("Illegal invocation of ".__METHOD__.".");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritdoc} */
|
/** {@inheritdoc} */
|
||||||
protected function _getInsertColumnList()
|
protected function _getInsertColumnList()
|
||||||
{
|
{
|
||||||
|
@ -232,6 +232,9 @@ final class Query extends AbstractQuery
|
|||||||
protected function _doExecute()
|
protected function _doExecute()
|
||||||
{
|
{
|
||||||
$executor = $this->_parse()->getSqlExecutor();
|
$executor = $this->_parse()->getSqlExecutor();
|
||||||
|
if ($this->_queryCacheProfile) {
|
||||||
|
$executor->setQueryCacheProfile($this->_queryCacheProfile);
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare parameters
|
// Prepare parameters
|
||||||
$paramMappings = $this->_parserResult->getParameterMappings();
|
$paramMappings = $this->_parserResult->getParameterMappings();
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* $Id$
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
@ -22,6 +20,7 @@
|
|||||||
namespace Doctrine\ORM\Query\Exec;
|
namespace Doctrine\ORM\Query\Exec;
|
||||||
|
|
||||||
use Doctrine\DBAL\Connection;
|
use Doctrine\DBAL\Connection;
|
||||||
|
use Doctrine\DBAL\Cache\QueryCacheProfile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for SQL statement executors.
|
* Base class for SQL statement executors.
|
||||||
@ -34,8 +33,16 @@ use Doctrine\DBAL\Connection;
|
|||||||
*/
|
*/
|
||||||
abstract class AbstractSqlExecutor
|
abstract class AbstractSqlExecutor
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
protected $_sqlStatements;
|
protected $_sqlStatements;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var QueryCacheProfile
|
||||||
|
*/
|
||||||
|
protected $queryCacheProfile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the SQL statements that are executed by the executor.
|
* Gets the SQL statements that are executed by the executor.
|
||||||
*
|
*
|
||||||
@ -46,12 +53,18 @@ abstract class AbstractSqlExecutor
|
|||||||
return $this->_sqlStatements;
|
return $this->_sqlStatements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setQueryCacheProfile(QueryCacheProfile $qcp)
|
||||||
|
{
|
||||||
|
$this->queryCacheProfile = $qcp;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes all sql statements.
|
* Executes all sql statements.
|
||||||
*
|
*
|
||||||
* @param Doctrine\DBAL\Connection $conn The database connection that is used to execute the queries.
|
* @param Doctrine\DBAL\Connection $conn The database connection that is used to execute the queries.
|
||||||
* @param array $params The parameters.
|
* @param array $params The parameters.
|
||||||
|
* @param array $types The parameter types.
|
||||||
* @return Doctrine\DBAL\Driver\Statement
|
* @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);
|
||||||
}
|
}
|
@ -1,7 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* $Id$
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
@ -32,7 +30,6 @@ use Doctrine\DBAL\Connection,
|
|||||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||||
* @link http://www.doctrine-project.org
|
* @link http://www.doctrine-project.org
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
class MultiTableDeleteExecutor extends AbstractSqlExecutor
|
class MultiTableDeleteExecutor extends AbstractSqlExecutor
|
||||||
{
|
{
|
||||||
@ -102,11 +99,7 @@ class MultiTableDeleteExecutor extends AbstractSqlExecutor
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes all SQL statements.
|
* {@inheritDoc}
|
||||||
*
|
|
||||||
* @param Doctrine\DBAL\Connection $conn The database connection that is used to execute the queries.
|
|
||||||
* @param array $params The parameters.
|
|
||||||
* @override
|
|
||||||
*/
|
*/
|
||||||
public function execute(Connection $conn, array $params, array $types)
|
public function execute(Connection $conn, array $params, array $types)
|
||||||
{
|
{
|
||||||
|
@ -141,11 +141,7 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes all SQL statements.
|
* {@inheritDoc}
|
||||||
*
|
|
||||||
* @param Connection $conn The database connection that is used to execute the queries.
|
|
||||||
* @param array $params The parameters.
|
|
||||||
* @override
|
|
||||||
*/
|
*/
|
||||||
public function execute(Connection $conn, array $params, array $types)
|
public function execute(Connection $conn, array $params, array $types)
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* $Id$
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
@ -30,7 +28,6 @@ use Doctrine\DBAL\Connection,
|
|||||||
*
|
*
|
||||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||||
* @author Roman Borschel <roman@code-factory.org>
|
* @author Roman Borschel <roman@code-factory.org>
|
||||||
* @version $Revision$
|
|
||||||
* @link www.doctrine-project.org
|
* @link www.doctrine-project.org
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
@ -41,8 +38,11 @@ class SingleSelectExecutor extends AbstractSqlExecutor
|
|||||||
$this->_sqlStatements = $sqlWalker->walkSelectStatement($AST);
|
$this->_sqlStatements = $sqlWalker->walkSelectStatement($AST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public function execute(Connection $conn, array $params, array $types)
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* $Id$
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
@ -30,7 +28,6 @@ use Doctrine\DBAL\Connection,
|
|||||||
*
|
*
|
||||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||||
* @author Roman Borschel <roman@code-factory.org>
|
* @author Roman Borschel <roman@code-factory.org>
|
||||||
* @version $Revision$
|
|
||||||
* @link www.doctrine-project.org
|
* @link www.doctrine-project.org
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
* @todo This is exactly the same as SingleSelectExecutor. Unify in SingleStatementExecutor.
|
* @todo This is exactly the same as SingleSelectExecutor. Unify in SingleStatementExecutor.
|
||||||
@ -45,7 +42,10 @@ class SingleTableDeleteUpdateExecutor extends AbstractSqlExecutor
|
|||||||
$this->_sqlStatements = $sqlWalker->walkDeleteStatement($AST);
|
$this->_sqlStatements = $sqlWalker->walkDeleteStatement($AST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public function execute(Connection $conn, array $params, array $types)
|
public function execute(Connection $conn, array $params, array $types)
|
||||||
{
|
{
|
||||||
return $conn->executeUpdate($this->_sqlStatements, $params, $types);
|
return $conn->executeUpdate($this->_sqlStatements, $params, $types);
|
||||||
|
@ -57,7 +57,7 @@ abstract class Base
|
|||||||
|
|
||||||
public function add($arg)
|
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 we decide to keep Expr\Base instances, we can use this check
|
||||||
if ( ! is_string($arg)) {
|
if ( ! is_string($arg)) {
|
||||||
$class = get_class($arg);
|
$class = get_class($arg);
|
||||||
|
@ -90,10 +90,10 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
public function testUseResultCache()
|
public function testUseResultCache()
|
||||||
{
|
{
|
||||||
$cache = new \Doctrine\Common\Cache\ArrayCache();
|
$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 = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
||||||
$query->useResultCache(true);
|
$query->useResultCache(true);
|
||||||
|
$query->setResultCacheDriver($cache);
|
||||||
$query->setResultCacheId('testing_result_cache_id');
|
$query->setResultCacheId('testing_result_cache_id');
|
||||||
$users = $query->getResult();
|
$users = $query->getResult();
|
||||||
|
|
||||||
@ -108,11 +108,11 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
public function testUseResultCacheParams()
|
public function testUseResultCacheParams()
|
||||||
{
|
{
|
||||||
$cache = new \Doctrine\Common\Cache\ArrayCache();
|
$cache = new \Doctrine\Common\Cache\ArrayCache();
|
||||||
$this->_em->getConfiguration()->setResultCacheImpl($cache);
|
|
||||||
|
|
||||||
$sqlCount = count($this->_sqlLoggerStack->queries);
|
$sqlCount = count($this->_sqlLoggerStack->queries);
|
||||||
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux WHERE ux.id = ?1');
|
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux WHERE ux.id = ?1');
|
||||||
$query->setParameter(1, 1);
|
$query->setParameter(1, 1);
|
||||||
|
$query->setResultCacheDriver($cache);
|
||||||
$query->useResultCache(true);
|
$query->useResultCache(true);
|
||||||
$query->getResult();
|
$query->getResult();
|
||||||
|
|
||||||
@ -149,10 +149,10 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param <type> $query
|
* @param string $query
|
||||||
* @depends testNativeQueryResultCaching
|
* @depends testNativeQueryResultCaching
|
||||||
*/
|
*/
|
||||||
public function testResultCacheDependsOnQueryHints($query)
|
public function testResultCacheNotDependsOnQueryHints($query)
|
||||||
{
|
{
|
||||||
$cache = $query->getResultCacheDriver();
|
$cache = $query->getResultCacheDriver();
|
||||||
$cacheCount = $this->getCacheSize($cache);
|
$cacheCount = $this->getCacheSize($cache);
|
||||||
@ -160,7 +160,7 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$query->setHint('foo', 'bar');
|
$query->setHint('foo', 'bar');
|
||||||
$query->getResult();
|
$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 <type> $query
|
* @param <type> $query
|
||||||
* @depends testNativeQueryResultCaching
|
* @depends testNativeQueryResultCaching
|
||||||
*/
|
*/
|
||||||
public function testResultCacheDependsOnHydrationMode($query)
|
public function testResultCacheNotDependsOnHydrationMode($query)
|
||||||
{
|
{
|
||||||
$cache = $query->getResultCacheDriver();
|
$cache = $query->getResultCacheDriver();
|
||||||
$cacheCount = $this->getCacheSize($cache);
|
$cacheCount = $this->getCacheSize($cache);
|
||||||
@ -190,7 +190,7 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$this->assertNotEquals(\Doctrine\ORM\Query::HYDRATE_ARRAY, $query->getHydrationMode());
|
$this->assertNotEquals(\Doctrine\ORM\Query::HYDRATE_ARRAY, $query->getHydrationMode());
|
||||||
$query->getArrayResult();
|
$query->getArrayResult();
|
||||||
|
|
||||||
$this->assertEquals($cacheCount + 1, $this->getCacheSize($cache));
|
$this->assertEquals($cacheCount, $this->getCacheSize($cache));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
69
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1454Test.php
Normal file
69
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1454Test.php
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||||
|
|
||||||
|
use Doctrine\ORM\UnitOfWork;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../../../TestInit.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-1454
|
||||||
|
*/
|
||||||
|
class DDC1454Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||||
|
{
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user