Merge pull request #1032 from bakura10/optimized-contains
Add support for optimized contains in LazyCriteria
This commit is contained in:
commit
38187a31d6
9 changed files with 77 additions and 24 deletions
10
UPGRADE.md
10
UPGRADE.md
|
@ -2,17 +2,17 @@
|
|||
|
||||
## Minor BC BREAK: Custom Hydrators API change
|
||||
|
||||
As of 2.5, `AbstractHydrator` does not enforce the usage of cache as part of
|
||||
As of 2.5, `AbstractHydrator` does not enforce the usage of cache as part of
|
||||
API, and now provides you a clean API for column information through the method
|
||||
`hydrateColumnInfo($column)`.
|
||||
Cache variable being passed around by reference is no longer needed since
|
||||
Cache variable being passed around by reference is no longer needed since
|
||||
Hydrators are per query instantiated since Doctrine 2.4.
|
||||
|
||||
## Minor BC BREAK: Entity based ``EntityManager#clear()`` calls follow cascade detach
|
||||
|
||||
Whenever ``EntityManager#clear()`` method gets called with a given entity class
|
||||
name, until 2.4, it was only detaching the specific requested entity.
|
||||
As of 2.5, ``EntityManager`` will follow configured cascades, providing a better
|
||||
Whenever ``EntityManager#clear()`` method gets called with a given entity class
|
||||
name, until 2.4, it was only detaching the specific requested entity.
|
||||
As of 2.5, ``EntityManager`` will follow configured cascades, providing a better
|
||||
memory management since associations will be garbage collected, optimizing
|
||||
resources consumption on long running jobs.
|
||||
|
||||
|
|
|
@ -191,9 +191,9 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function exists($entity, array $extraConditions = array())
|
||||
public function exists($entity, Criteria $extraConditions = null)
|
||||
{
|
||||
if (empty($extraConditions)) {
|
||||
if (null === $extraConditions) {
|
||||
$key = new EntityCacheKey($this->class->rootEntityName, $this->class->getIdentifierValues($entity));
|
||||
|
||||
if ($this->region->contains($key)) {
|
||||
|
|
|
@ -30,7 +30,7 @@ use Doctrine\ORM\Persisters\EntityPersister;
|
|||
* A lazy collection that allow a fast count when using criteria object
|
||||
* Once count gets executed once without collection being initialized, result
|
||||
* is cached and returned on subsequent calls until collection gets loaded,
|
||||
* then returning the number of loaded results.
|
||||
* then returning the number of loaded results.
|
||||
*
|
||||
* @since 2.5
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
|
@ -82,6 +82,21 @@ class LazyCriteriaCollection extends AbstractLazyCollection implements Selectabl
|
|||
return $this->count = $this->entityPersister->count($this->criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do an optimized search of an element
|
||||
*
|
||||
* @param object $element
|
||||
* @return bool
|
||||
*/
|
||||
public function contains($element)
|
||||
{
|
||||
if ($this->isInitialized()) {
|
||||
return $this->collection->contains($element);
|
||||
}
|
||||
|
||||
return $this->entityPersister->exists($element, $this->criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
|
|
@ -1835,7 +1835,7 @@ class BasicEntityPersister implements EntityPersister
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function exists($entity, array $extraConditions = array())
|
||||
public function exists($entity, Criteria $extraConditions = null)
|
||||
{
|
||||
$criteria = $this->class->getIdentifierValues($entity);
|
||||
|
||||
|
@ -1843,22 +1843,25 @@ class BasicEntityPersister implements EntityPersister
|
|||
return false;
|
||||
}
|
||||
|
||||
if ($extraConditions) {
|
||||
$criteria = array_merge($criteria, $extraConditions);
|
||||
}
|
||||
|
||||
$alias = $this->getSQLTableAlias($this->class->name);
|
||||
|
||||
$sql = 'SELECT 1 '
|
||||
. $this->getLockTablesSql(null)
|
||||
. ' WHERE ' . $this->getSelectConditionSQL($criteria);
|
||||
|
||||
list($params) = $this->expandParameters($criteria);
|
||||
|
||||
if (null !== $extraConditions) {
|
||||
$sql .= ' AND ' . $this->getSelectConditionCriteriaSQL($extraConditions);
|
||||
list($criteriaParams, $values) = $this->expandCriteriaParameters($extraConditions);
|
||||
|
||||
$params = array_merge($params, $criteriaParams);
|
||||
}
|
||||
|
||||
if ($filterSql = $this->generateFilterConditionSQL($this->class, $alias)) {
|
||||
$sql .= ' AND ' . $filterSql;
|
||||
}
|
||||
|
||||
list($params) = $this->expandParameters($criteria);
|
||||
|
||||
return (bool) $this->conn->fetchColumn($sql, $params);
|
||||
}
|
||||
|
||||
|
|
|
@ -319,10 +319,10 @@ interface EntityPersister
|
|||
/**
|
||||
* Checks whether the given managed entity exists in the database.
|
||||
*
|
||||
* @param object $entity
|
||||
* @param array $extraConditions
|
||||
* @param object $entity
|
||||
* @param Criteria|null $extraConditions
|
||||
*
|
||||
* @return boolean TRUE if the entity exists in the database, FALSE otherwise.
|
||||
*/
|
||||
public function exists($entity, array $extraConditions = array());
|
||||
public function exists($entity, Criteria $extraConditions = null);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
namespace Doctrine\ORM\Persisters;
|
||||
|
||||
use Doctrine\Common\Collections\Criteria;
|
||||
use Doctrine\ORM\PersistentCollection;
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
|
||||
|
@ -168,7 +169,7 @@ class OneToManyPersister extends AbstractCollectionPersister
|
|||
|
||||
return (bool) $this->conn->fetchColumn($sql, $params);
|
||||
}
|
||||
|
||||
|
||||
private function getJoinTableRestrictions(PersistentCollection $coll, $addFilters)
|
||||
{
|
||||
$mapping = $coll->getMapping();
|
||||
|
@ -227,9 +228,9 @@ class OneToManyPersister extends AbstractCollectionPersister
|
|||
// only works with single id identifier entities. Will throw an
|
||||
// exception in Entity Persisters if that is not the case for the
|
||||
// 'mappedBy' field.
|
||||
$id = current($uow->getEntityIdentifier($coll->getOwner()));
|
||||
$criteria = new Criteria(Criteria::expr()->eq($mapping['mappedBy'], $coll->getOwner()));
|
||||
|
||||
return $persister->exists($element, array($mapping['mappedBy'] => $id));
|
||||
return $persister->exists($element, $criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Doctrine\Tests\Mocks;
|
||||
use Doctrine\Common\Collections\Criteria;
|
||||
|
||||
/**
|
||||
* EntityPersister implementation used for mocking during tests.
|
||||
|
@ -88,7 +89,7 @@ class EntityPersisterMock extends \Doctrine\ORM\Persisters\BasicEntityPersister
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function exists($entity, array $extraConditions = array())
|
||||
public function exists($entity, Criteria $extraConditions = null)
|
||||
{
|
||||
$this->existsCalled = true;
|
||||
}
|
||||
|
|
|
@ -433,8 +433,8 @@ abstract class AbstractEntityPersisterTest extends OrmTestCase
|
|||
|
||||
$this->entityPersister->expects($this->once())
|
||||
->method('exists')
|
||||
->with($this->equalTo($entity), $this->equalTo(array()));
|
||||
->with($this->equalTo($entity), $this->equalTo(null));
|
||||
|
||||
$this->assertNull($persister->exists($entity, array()));
|
||||
$this->assertNull($persister->exists($entity));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ namespace Doctrine\Tests\ORM\Functional;
|
|||
|
||||
use Doctrine\Tests\Models\Generic\DateTimeModel;
|
||||
use Doctrine\Common\Collections\Criteria;
|
||||
use Doctrine\Tests\Models\Tweet\Tweet;
|
||||
use Doctrine\Tests\Models\Tweet\User;
|
||||
|
||||
/**
|
||||
* @author Josiah <josiah@jjs.id.au>
|
||||
|
@ -30,6 +32,7 @@ class EntityRepositoryCriteriaTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||
protected function setUp()
|
||||
{
|
||||
$this->useModelSet('generic');
|
||||
$this->useModelSet('tweet');
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
|
@ -165,4 +168,34 @@ class EntityRepositoryCriteriaTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||
$date = $dates[0];
|
||||
$this->assertTrue($dates->isInitialized());
|
||||
}
|
||||
|
||||
public function testCanContainsWithoutLoadingCollection()
|
||||
{
|
||||
$user = new User();
|
||||
$user->name = 'Marco';
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
|
||||
$tweet = new Tweet();
|
||||
$tweet->author = $user;
|
||||
$tweet->content = 'Criteria is awesome';
|
||||
$this->_em->persist($tweet);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
$criteria = new Criteria();
|
||||
$criteria->andWhere($criteria->expr()->contains('content', 'Criteria'));
|
||||
|
||||
$user = $this->_em->find('Doctrine\Tests\Models\Tweet\User', $user->id);
|
||||
$tweets = $user->tweets->matching($criteria);
|
||||
|
||||
$this->assertInstanceOf('Doctrine\ORM\LazyCriteriaCollection', $tweets);
|
||||
$this->assertFalse($tweets->isInitialized());
|
||||
|
||||
$tweets->contains($tweet);
|
||||
$this->assertTrue($tweets->contains($tweet));
|
||||
|
||||
$this->assertFalse($tweets->isInitialized());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue