DDC-546 - Add Extra Lazy Collection prototype.
This commit is contained in:
parent
78d4277e4b
commit
c998797c55
@ -121,6 +121,12 @@ class ClassMetadataInfo
|
||||
* association is fetched.
|
||||
*/
|
||||
const FETCH_EAGER = 3;
|
||||
/**
|
||||
* Specifies that an association is to be fetched lazy (on first access) and that
|
||||
* commands such as Collection#count, Collection#slice are issued directly against
|
||||
* the database if the collection is not yet initialized.
|
||||
*/
|
||||
const FETCH_EXTRALAZY = 4;
|
||||
/**
|
||||
* Identifies a one-to-one association.
|
||||
*/
|
||||
|
@ -59,16 +59,16 @@ final class PersistentCollection implements Collection
|
||||
* The association mapping the collection belongs to.
|
||||
* This is currently either a OneToManyMapping or a ManyToManyMapping.
|
||||
*
|
||||
* @var Doctrine\ORM\Mapping\AssociationMapping
|
||||
* @var array
|
||||
*/
|
||||
private $association;
|
||||
protected $association;
|
||||
|
||||
/**
|
||||
* The EntityManager that manages the persistence of the collection.
|
||||
*
|
||||
* @var Doctrine\ORM\EntityManager
|
||||
*/
|
||||
private $em;
|
||||
protected $em;
|
||||
|
||||
/**
|
||||
* The name of the field on the target entities that points to the owner
|
||||
@ -96,7 +96,7 @@ final class PersistentCollection implements Collection
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private $initialized = true;
|
||||
protected $initialized = true;
|
||||
|
||||
/**
|
||||
* The wrapped Collection instance.
|
||||
@ -475,6 +475,17 @@ final class PersistentCollection implements Collection
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
if (!$this->initialized && $this->association['fetch'] == Mapping\ClassMetadataInfo::FETCH_EXTRALAZY) {
|
||||
// use a dynamic public property here. That may be slower, but its not using so much
|
||||
// memory as having a count variable in each collection.
|
||||
if (!isset($this->doctrineCollectionCount)) {
|
||||
$this->doctrineCollectionCount = $this->em->getUnitOfWork()
|
||||
->getCollectionPersister($this->association)
|
||||
->count($this) + count ($this->coll->toArray());
|
||||
}
|
||||
return $this->doctrineCollectionCount;
|
||||
}
|
||||
|
||||
$this->initialize();
|
||||
return $this->coll->count();
|
||||
}
|
||||
@ -675,6 +686,12 @@ final class PersistentCollection implements Collection
|
||||
*/
|
||||
public function slice($offset, $length = null)
|
||||
{
|
||||
if (!$this->initialized && $this->association['fetch'] == Mapping\ClassMetadataInfo::FETCH_EXTRALAZY) {
|
||||
return $this->em->getUnitOfWork()
|
||||
->getCollectionPersister($this->association)
|
||||
->slice($this, $offset, $length);
|
||||
}
|
||||
|
||||
$this->initialize();
|
||||
return $this->coll->slice($offset, $length);
|
||||
}
|
||||
|
@ -125,6 +125,31 @@ abstract class AbstractCollectionPersister
|
||||
}
|
||||
}
|
||||
|
||||
public function count(PersistentCollection $coll)
|
||||
{
|
||||
throw new \BadMethodCallException("Counting the size of this persistent collection is not supported by this CollectionPersister.");
|
||||
}
|
||||
|
||||
public function slice(PersistentCollection $coll, $offset, $length = null)
|
||||
{
|
||||
throw new \BadMethodCallException("Slicing elements is not supported by this CollectionPersister.");
|
||||
}
|
||||
|
||||
public function contains(PersistentCollection $coll, $key)
|
||||
{
|
||||
throw new \BadMethodCallException("Checking for existance of an element is not supported by this CollectionPersister.");
|
||||
}
|
||||
|
||||
public function containsKey(PersistentCollection $coll, $element)
|
||||
{
|
||||
throw new \BadMethodCallException("Checking for existance of a key is not supported by this CollectionPersister.");
|
||||
}
|
||||
|
||||
public function get(PersistentCollection $coll, $index)
|
||||
{
|
||||
throw new \BadMethodCallException("Selecting a collection by index is not supported by this CollectionPersister.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SQL statement used for deleting a row from the collection.
|
||||
*
|
||||
|
@ -723,9 +723,12 @@ class BasicEntityPersister
|
||||
* @param ManyToManyMapping $assoc The association mapping of the association being loaded.
|
||||
* @param object $sourceEntity The entity that owns the collection.
|
||||
* @param PersistentCollection $coll The collection to fill.
|
||||
* @param int|null $offset
|
||||
* @param int|null $limit
|
||||
* @return array
|
||||
*/
|
||||
public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
|
||||
{
|
||||
public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll = null, $offset = null, $limit = null)
|
||||
{
|
||||
$criteria = array();
|
||||
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
|
||||
$joinTableConditions = array();
|
||||
@ -772,10 +775,17 @@ class BasicEntityPersister
|
||||
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc);
|
||||
list($params, $types) = $this->expandParameters($criteria);
|
||||
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
||||
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$coll->hydrateAdd($this->_createEntity($result));
|
||||
if ($coll) {
|
||||
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$coll->hydrateAdd($this->_createEntity($result));
|
||||
}
|
||||
} else {
|
||||
$entities = array();
|
||||
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$entities[] = $this->_createEntity($result);
|
||||
}
|
||||
return $entities;
|
||||
}
|
||||
$stmt->closeCursor();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -854,7 +864,7 @@ class BasicEntityPersister
|
||||
* @return string
|
||||
* @todo Refactor: _getSelectSQL(...)
|
||||
*/
|
||||
protected function _getSelectEntitiesSQL(array $criteria, $assoc = null, $lockMode = 0)
|
||||
protected function _getSelectEntitiesSQL(array $criteria, $assoc = null, $lockMode = 0, $limit = null, $offset = null)
|
||||
{
|
||||
$joinSql = $assoc != null && $assoc['type'] == ClassMetadata::MANY_TO_MANY ?
|
||||
$this->_getSelectManyToManyJoinSQL($assoc) : '';
|
||||
@ -872,12 +882,12 @@ class BasicEntityPersister
|
||||
$lockSql = ' ' . $this->_platform->getWriteLockSql();
|
||||
}
|
||||
|
||||
return 'SELECT ' . $this->_getSelectColumnListSQL()
|
||||
return $this->_platform->modifyLimitQuery('SELECT ' . $this->_getSelectColumnListSQL()
|
||||
. $this->_platform->appendLockHint(' FROM ' . $this->_class->getQuotedTableName($this->_platform) . ' '
|
||||
. $this->_getSQLTableAlias($this->_class->name), $lockMode)
|
||||
. $joinSql
|
||||
. ($conditionSql ? ' WHERE ' . $conditionSql : '')
|
||||
. $orderBySql
|
||||
. $orderBySql, $limit, $offset)
|
||||
. $lockSql;
|
||||
}
|
||||
|
||||
@ -1181,8 +1191,10 @@ class BasicEntityPersister
|
||||
* @param OneToManyMapping $assoc
|
||||
* @param array $criteria The criteria by which to select the entities.
|
||||
* @param PersistentCollection The collection to load/fill.
|
||||
* @param int|null $offset
|
||||
* @param int|null $limit
|
||||
*/
|
||||
public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
|
||||
public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll = null, $offset = null, $limit = null)
|
||||
{
|
||||
$criteria = array();
|
||||
$owningAssoc = $this->_class->associationMappings[$assoc['mappedBy']];
|
||||
@ -1204,10 +1216,17 @@ class BasicEntityPersister
|
||||
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc);
|
||||
list($params, $types) = $this->expandParameters($criteria);
|
||||
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
||||
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$coll->hydrateAdd($this->_createEntity($result));
|
||||
if ($coll) {
|
||||
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$coll->hydrateAdd($this->_createEntity($result));
|
||||
}
|
||||
} else {
|
||||
$entities = array();
|
||||
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$entities[] = $this->_createEntity($result);
|
||||
}
|
||||
return $entities;
|
||||
}
|
||||
$stmt->closeCursor();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1252,4 +1271,6 @@ class BasicEntityPersister
|
||||
{
|
||||
|
||||
}*/
|
||||
|
||||
#public function countCollection
|
||||
}
|
||||
|
@ -20,7 +20,8 @@
|
||||
namespace Doctrine\ORM\Persisters;
|
||||
|
||||
use Doctrine\ORM\ORMException,
|
||||
Doctrine\ORM\Mapping\ClassMetadata;
|
||||
Doctrine\ORM\Mapping\ClassMetadata,
|
||||
Doctrine\DBAL\LockMode;
|
||||
|
||||
/**
|
||||
* The joined subclass persister maps a single entity instance to several tables in the
|
||||
@ -239,7 +240,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _getSelectEntitiesSQL(array $criteria, $assoc = null, $lockMode = 0)
|
||||
protected function _getSelectEntitiesSQL(array $criteria, $assoc = null, $lockMode = 0, $limit = null, $offset = null)
|
||||
{
|
||||
$idColumns = $this->_class->getIdentifierColumnNames();
|
||||
$baseTableAlias = $this->_getSQLTableAlias($this->_class->name);
|
||||
@ -348,10 +349,18 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
$this->_selectColumnListSql = $columnList;
|
||||
}
|
||||
|
||||
return 'SELECT ' . $this->_selectColumnListSql
|
||||
$lockSql = '';
|
||||
if ($lockMode == LockMode::PESSIMISTIC_READ) {
|
||||
$lockSql = ' ' . $this->_platform->getReadLockSql();
|
||||
} else if ($lockMode == LockMode::PESSIMISTIC_WRITE) {
|
||||
$lockSql = ' ' . $this->_platform->getWriteLockSql();
|
||||
}
|
||||
|
||||
return $this->_platform->modifyLimitQuery('SELECT ' . $this->_selectColumnListSql
|
||||
. ' FROM ' . $this->_class->getQuotedTableName($this->_platform) . ' ' . $baseTableAlias
|
||||
. $joinSql
|
||||
. ($conditionSql != '' ? ' WHERE ' . $conditionSql : '') . $orderBySql;
|
||||
. ($conditionSql != '' ? ' WHERE ' . $conditionSql : '') . $orderBySql, $limit, $offset)
|
||||
. $lockSql;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -181,4 +181,53 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function count(PersistentCollection $coll)
|
||||
{
|
||||
$params = array();
|
||||
$mapping = $coll->getMapping();
|
||||
$class = $this->_em->getClassMetadata($mapping['sourceEntity']);
|
||||
$id = $this->_em->getUnitOfWork()->getEntityIdentifier($coll->getOwner());
|
||||
|
||||
if ($mapping['isOwningSide']) {
|
||||
$joinTable = $mapping['joinTable'];
|
||||
$joinColumns = $mapping['relationToSourceKeyColumns'];
|
||||
} else {
|
||||
$mapping = $this->_em->getClassMetadata($mapping['targetEntity'])->associationMappings[$mapping['mappedBy']];
|
||||
$joinTable = $mapping['joinTable'];
|
||||
$joinColumns = $mapping['relationToTargetKeyColumns'];
|
||||
}
|
||||
|
||||
$whereClause = '';
|
||||
foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
|
||||
if (isset($joinColumns[$joinTableColumn])) {
|
||||
if ($whereClause !== '') {
|
||||
$whereClause .= ' AND ';
|
||||
}
|
||||
$whereClause .= "$joinTableColumn = ?";
|
||||
|
||||
$params[] = $id[$class->fieldNames[$joinColumns[$joinTableColumn]]];
|
||||
}
|
||||
}
|
||||
$sql = 'SELECT count(*) FROM ' . $joinTable['name'] . ' WHERE ' . $whereClause;
|
||||
|
||||
return $this->_conn->fetchColumn($sql, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PersistentCollection $coll
|
||||
* @param int $offset
|
||||
* @param int $length
|
||||
* @return array
|
||||
*/
|
||||
public function slice(PersistentCollection $coll, $offset, $length = null)
|
||||
{
|
||||
$mapping = $coll->getMapping();
|
||||
return $this->_em->getUnitOfWork()
|
||||
->getEntityPersister($mapping['targetEntity'])
|
||||
->loadManyToManyCollection($mapping, $coll->getOwner(), null, $offset, $length);
|
||||
}
|
||||
}
|
@ -116,4 +116,41 @@ class OneToManyPersister extends AbstractCollectionPersister
|
||||
*/
|
||||
protected function _getDeleteRowSQLParameters(PersistentCollection $coll, $element)
|
||||
{}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function count(PersistentCollection $coll)
|
||||
{
|
||||
$mapping = $coll->getMapping();
|
||||
$class = $this->_em->getClassMetadata($mapping['targetEntity']);
|
||||
$params = array();
|
||||
$id = $this->_em->getUnitOfWork()->getEntityIdentifier($coll->getOwner());
|
||||
|
||||
$where = '';
|
||||
foreach ($class->associationMappings[$mapping['mappedBy']]['joinColumns'] AS $joinColumn) {
|
||||
if ($where != '') {
|
||||
$where .= ' AND ';
|
||||
}
|
||||
$where .= $joinColumn['name'] . " = ?";
|
||||
$params[] = $id[$class->fieldNames[$joinColumn['referencedColumnName']]];
|
||||
}
|
||||
|
||||
$sql = "SELECT count(*) FROM " . $class->getQuotedTableName($this->_conn->getDatabasePlatform()) . " WHERE " . $where;
|
||||
return $this->_conn->fetchColumn($sql, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PersistentCollection $coll
|
||||
* @param int $offset
|
||||
* @param int $length
|
||||
* @return \Doctrine\Common\Collections\ArrayCollection
|
||||
*/
|
||||
public function slice(PersistentCollection $coll, $offset, $length = null)
|
||||
{
|
||||
$mapping = $coll->getMapping();
|
||||
return $this->_em->getUnitOfWork()
|
||||
->getEntityPersister($mapping['targetEntity'])
|
||||
->loadOneToManyCollection($mapping, $coll->getOwner(), null, $offset, $length);
|
||||
}
|
||||
}
|
@ -1958,11 +1958,11 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$reflField = $class->reflFields[$field];
|
||||
$reflField->setValue($entity, $pColl);
|
||||
|
||||
if ($assoc['fetch'] == ClassMetadata::FETCH_LAZY) {
|
||||
$pColl->setInitialized(false);
|
||||
} else {
|
||||
if ($assoc['fetch'] == ClassMetadata::FETCH_EAGER) {
|
||||
$this->loadCollection($pColl);
|
||||
$pColl->takeSnapshot();
|
||||
} else {
|
||||
$pColl->setInitialized(false);
|
||||
}
|
||||
$this->originalEntityData[$oid][$field] = $pColl;
|
||||
}
|
||||
@ -2123,7 +2123,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
* Gets the EntityPersister for an Entity.
|
||||
*
|
||||
* @param string $entityName The name of the Entity.
|
||||
* @return Doctrine\ORM\Persister\AbstractEntityPersister
|
||||
* @return Doctrine\ORM\Persisters\AbstractEntityPersister
|
||||
*/
|
||||
public function getEntityPersister($entityName)
|
||||
{
|
||||
|
@ -55,6 +55,7 @@ class AllTests
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\IdentityMapTest');
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\DatabaseDriverTest');
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\PostgreSQLIdentityStrategyTest');
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\ExtraLazyCollectionTest');
|
||||
|
||||
$suite->addTest(Locking\AllTests::suite());
|
||||
$suite->addTest(Ticket\AllTests::suite());
|
||||
|
@ -9,8 +9,6 @@ use Doctrine\Tests\Models\CMS\CmsAddress;
|
||||
require_once __DIR__ . '/../../TestInit.php';
|
||||
|
||||
/**
|
||||
* Description of DetachedEntityTest
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
284
tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
Normal file
284
tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
Normal file
@ -0,0 +1,284 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional;
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||
|
||||
require_once __DIR__ . '/../../TestInit.php';
|
||||
|
||||
/**
|
||||
* Description of ExtraLazyCollectionTest
|
||||
*
|
||||
* @author beberlei
|
||||
*/
|
||||
class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
private $userId;
|
||||
private $groupId;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->useModelSet('cms');
|
||||
parent::setUp();
|
||||
|
||||
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
|
||||
$class->associationMappings['groups']['fetch'] = ClassMetadataInfo::FETCH_EXTRALAZY;
|
||||
$class->associationMappings['articles']['fetch'] = ClassMetadataInfo::FETCH_EXTRALAZY;
|
||||
|
||||
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsGroup');
|
||||
$class->associationMappings['users']['fetch'] = ClassMetadataInfo::FETCH_EXTRALAZY;
|
||||
|
||||
$this->loadFixture();
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
parent::tearDown();
|
||||
|
||||
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
|
||||
$class->associationMappings['groups']['fetch'] = ClassMetadataInfo::FETCH_LAZY;
|
||||
$class->associationMappings['articles']['fetch'] = ClassMetadataInfo::FETCH_LAZY;
|
||||
|
||||
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsGroup');
|
||||
$class->associationMappings['users']['fetch'] = ClassMetadataInfo::FETCH_LAZY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-546
|
||||
*/
|
||||
public function testCountNotInitializesCollection()
|
||||
{
|
||||
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
|
||||
$queryCount = $this->getCurrentQueryCount();
|
||||
|
||||
$this->assertFalse($user->groups->isInitialized());
|
||||
$this->assertEquals(3, count($user->groups));
|
||||
$this->assertFalse($user->groups->isInitialized());
|
||||
|
||||
foreach ($user->groups AS $group) { }
|
||||
|
||||
$this->assertEquals($queryCount + 2, $this->getCurrentQueryCount(), "Expecting two queries to be fired for count, then iteration.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-546
|
||||
*/
|
||||
public function testCountWhenNewEntitysPresent()
|
||||
{
|
||||
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
|
||||
|
||||
$newGroup = new \Doctrine\Tests\Models\CMS\CmsGroup();
|
||||
$newGroup->name = "Test4";
|
||||
|
||||
$user->addGroup($newGroup);
|
||||
$this->_em->persist($newGroup);
|
||||
|
||||
$this->assertFalse($user->groups->isInitialized());
|
||||
$this->assertEquals(4, count($user->groups));
|
||||
$this->assertFalse($user->groups->isInitialized());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-546
|
||||
*/
|
||||
public function testCountWhenInitialized()
|
||||
{
|
||||
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
|
||||
$queryCount = $this->getCurrentQueryCount();
|
||||
|
||||
foreach ($user->groups AS $group) { }
|
||||
|
||||
$this->assertTrue($user->groups->isInitialized());
|
||||
$this->assertEquals(3, count($user->groups));
|
||||
$this->assertEquals($queryCount + 1, $this->getCurrentQueryCount(), "Should only execute one query to initialize colleciton, no extra query for count() more.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-546
|
||||
*/
|
||||
public function testCountInverseCollection()
|
||||
{
|
||||
$group = $this->_em->find('Doctrine\Tests\Models\CMS\CmsGroup', $this->groupId);
|
||||
$this->assertFalse($group->users->isInitialized(), "Pre-Condition");
|
||||
|
||||
$this->assertEquals(4, count($group->users));
|
||||
$this->assertFalse($group->users->isInitialized(), "Extra Lazy collection should not be initialized by counting the collection.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-546
|
||||
*/
|
||||
public function testCountOneToMany()
|
||||
{
|
||||
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
|
||||
$this->assertFalse($user->groups->isInitialized(), "Pre-Condition");
|
||||
|
||||
$this->assertEquals(2, count($user->articles));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-546
|
||||
*/
|
||||
public function testFullSlice()
|
||||
{
|
||||
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
|
||||
$this->assertFalse($user->groups->isInitialized(), "Pre-Condition: Collection is not initialized.");
|
||||
|
||||
$someGroups = $user->groups->slice(null);
|
||||
$this->assertEquals(3, count($someGroups));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-546
|
||||
*/
|
||||
public function testSlice()
|
||||
{
|
||||
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
|
||||
$this->assertFalse($user->groups->isInitialized(), "Pre-Condition: Collection is not initialized.");
|
||||
|
||||
$queryCount = $this->getCurrentQueryCount();
|
||||
|
||||
$someGroups = $user->groups->slice(0, 2);
|
||||
|
||||
$this->assertContainsOnly('Doctrine\Tests\Models\CMS\CmsGroup', $someGroups);
|
||||
$this->assertEquals(2, count($someGroups));
|
||||
$this->assertFalse($user->groups->isInitialized(), "Slice should not initialize the collection if it wasn't before!");
|
||||
|
||||
$otherGroup = $user->groups->slice(2, 1);
|
||||
|
||||
$this->assertContainsOnly('Doctrine\Tests\Models\CMS\CmsGroup', $otherGroup);
|
||||
$this->assertEquals(1, count($otherGroup));
|
||||
$this->assertFalse($user->groups->isInitialized());
|
||||
|
||||
foreach ($user->groups AS $group) { }
|
||||
|
||||
$this->assertTrue($user->groups->isInitialized());
|
||||
$this->assertEquals(3, count($user->groups));
|
||||
|
||||
$this->assertEquals($queryCount + 3, $this->getCurrentQueryCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-546
|
||||
*/
|
||||
public function testSliceInitializedCollection()
|
||||
{
|
||||
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
|
||||
$queryCount = $this->getCurrentQueryCount();
|
||||
|
||||
foreach ($user->groups AS $group) { }
|
||||
|
||||
$someGroups = $user->groups->slice(0, 2);
|
||||
|
||||
$this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
|
||||
|
||||
$this->assertEquals(2, count($someGroups));
|
||||
$this->assertTrue($user->groups->contains($someGroups[0]));
|
||||
$this->assertTrue($user->groups->contains($someGroups[1]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-546
|
||||
*/
|
||||
public function testSliceInverseCollection()
|
||||
{
|
||||
$group = $this->_em->find('Doctrine\Tests\Models\CMS\CmsGroup', $this->groupId);
|
||||
$this->assertFalse($group->users->isInitialized(), "Pre-Condition");
|
||||
$queryCount = $this->getCurrentQueryCount();
|
||||
|
||||
$someUsers = $group->users->slice(0, 2);
|
||||
$otherUsers = $group->users->slice(2, 2);
|
||||
|
||||
$this->assertContainsOnly('Doctrine\Tests\Models\CMS\CmsUser', $someUsers);
|
||||
$this->assertContainsOnly('Doctrine\Tests\Models\CMS\CmsUser', $otherUsers);
|
||||
$this->assertEquals(2, count($someUsers));
|
||||
$this->assertEquals(2, count($otherUsers));
|
||||
|
||||
// +2 queries executed by slice, +4 are executed by EAGER fetching of User Address.
|
||||
$this->assertEquals($queryCount + 2 + 4, $this->getCurrentQueryCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-546
|
||||
*/
|
||||
public function testSliceOneToMany()
|
||||
{
|
||||
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
|
||||
$this->assertFalse($user->articles->isInitialized(), "Pre-Condition: Collection is not initialized.");
|
||||
|
||||
$queryCount = $this->getCurrentQueryCount();
|
||||
|
||||
$someArticle = $user->articles->slice(0, 1);
|
||||
$otherArticle = $user->articles->slice(1, 1);
|
||||
|
||||
$this->assertEquals($queryCount + 2, $this->getCurrentQueryCount());
|
||||
}
|
||||
|
||||
private function loadFixture()
|
||||
{
|
||||
$user1 = new \Doctrine\Tests\Models\CMS\CmsUser();
|
||||
$user1->username = "beberlei";
|
||||
$user1->name = "Benjamin";
|
||||
$user1->status = "active";
|
||||
|
||||
$user2 = new \Doctrine\Tests\Models\CMS\CmsUser();
|
||||
$user2->username = "jwage";
|
||||
$user2->name = "Jonathan";
|
||||
$user2->status = "active";
|
||||
|
||||
$user3 = new \Doctrine\Tests\Models\CMS\CmsUser();
|
||||
$user3->username = "romanb";
|
||||
$user3->name = "Roman";
|
||||
$user3->status = "active";
|
||||
|
||||
$user4 = new \Doctrine\Tests\Models\CMS\CmsUser();
|
||||
$user4->username = "gblanco";
|
||||
$user4->name = "Guilherme";
|
||||
$user4->status = "active";
|
||||
|
||||
$this->_em->persist($user1);
|
||||
$this->_em->persist($user2);
|
||||
$this->_em->persist($user3);
|
||||
$this->_em->persist($user4);
|
||||
|
||||
$group1 = new \Doctrine\Tests\Models\CMS\CmsGroup();
|
||||
$group1->name = "Test1";
|
||||
|
||||
$group2 = new \Doctrine\Tests\Models\CMS\CmsGroup();
|
||||
$group2->name = "Test2";
|
||||
|
||||
$group3 = new \Doctrine\Tests\Models\CMS\CmsGroup();
|
||||
$group3->name = "Test3";
|
||||
|
||||
$user1->addGroup($group1);
|
||||
$user1->addGroup($group2);
|
||||
$user1->addGroup($group3);
|
||||
|
||||
$user2->addGroup($group1);
|
||||
$user3->addGroup($group1);
|
||||
$user4->addGroup($group1);
|
||||
|
||||
$this->_em->persist($group1);
|
||||
$this->_em->persist($group2);
|
||||
$this->_em->persist($group3);
|
||||
|
||||
$article1 = new \Doctrine\Tests\Models\CMS\CmsArticle();
|
||||
$article1->topic = "Test";
|
||||
$article1->text = "Test";
|
||||
$article1->setAuthor($user1);
|
||||
|
||||
$article2 = new \Doctrine\Tests\Models\CMS\CmsArticle();
|
||||
$article2->topic = "Test";
|
||||
$article2->text = "Test";
|
||||
$article2->setAuthor($user1);
|
||||
|
||||
$this->_em->persist($article1);
|
||||
$this->_em->persist($article2);
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$this->userId = $user1->getId();
|
||||
$this->groupId = $group1->id;
|
||||
}
|
||||
}
|
@ -314,4 +314,14 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Using the SQL Logger Stack this method retrieves the current query count executed in this test.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function getCurrentQueryCount()
|
||||
{
|
||||
return count($this->_sqlLoggerStack->queries);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user