1
0
mirror of synced 2025-01-18 06:21:40 +03:00

Merge pull request #97 from asm89/DDC-1301

[DDC-1301] Fixed count() for fetch="EXTRA_LAZY" on OneToMany association
This commit is contained in:
Benjamin Eberlei 2011-07-28 14:26:15 -07:00
commit 5c47c07794
7 changed files with 388 additions and 7 deletions

View File

@ -124,24 +124,26 @@ class OneToManyPersister extends AbstractCollectionPersister
public function count(PersistentCollection $coll)
{
$mapping = $coll->getMapping();
$class = $this->_em->getClassMetadata($mapping['targetEntity']);
$targetClass = $this->_em->getClassMetadata($mapping['targetEntity']);
$sourceClass = $this->_em->getClassMetadata($mapping['sourceEntity']);
$params = array();
$id = $this->_em->getUnitOfWork()->getEntityIdentifier($coll->getOwner());
$where = '';
foreach ($class->associationMappings[$mapping['mappedBy']]['joinColumns'] AS $joinColumn) {
foreach ($targetClass->associationMappings[$mapping['mappedBy']]['joinColumns'] AS $joinColumn) {
if ($where != '') {
$where .= ' AND ';
}
$where .= $joinColumn['name'] . " = ?";
if ($class->containsForeignIdentifier) {
$params[] = $id[$class->getFieldForColumn($joinColumn['referencedColumnName'])];
if ($targetClass->containsForeignIdentifier) {
$params[] = $id[$sourceClass->getFieldForColumn($joinColumn['referencedColumnName'])];
} else {
$params[] = $id[$class->fieldNames[$joinColumn['referencedColumnName']]];
$params[] = $id[$sourceClass->fieldNames[$joinColumn['referencedColumnName']]];
}
}
$sql = "SELECT count(*) FROM " . $class->getQuotedTableName($this->_conn->getDatabasePlatform()) . " WHERE " . $where;
$sql = "SELECT count(*) FROM " . $targetClass->getQuotedTableName($this->_conn->getDatabasePlatform()) . " WHERE " . $where;
return $this->_conn->fetchColumn($sql, $params);
}
@ -180,4 +182,4 @@ class OneToManyPersister extends AbstractCollectionPersister
return $uow->getEntityPersister($mapping['targetEntity'])
->exists($element, array($mapping['mappedBy'] => $id));
}
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace Doctrine\Tests\Models\Legacy;
/**
* @Entity
* @Table(name="legacy_articles")
*/
class LegacyArticle
{
/**
* @Id
* @Column(name="iArticleId", type="integer")
* @GeneratedValue(strategy="AUTO")
*/
public $_id;
/**
* @Column(name="sTopic", type="string", length=255)
*/
public $_topic;
/**
* @Column(name="sText", type="text")
*/
public $_text;
/**
* @ManyToOne(targetEntity="LegacyUser", inversedBy="_articles")
* @JoinColumn(name="iUserId", referencedColumnName="iUserId")
*/
public $_user;
public function setAuthor(LegacyUser $author) {
$this->_user = $author;
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace Doctrine\Tests\Models\Legacy;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @Entity
* @Table(name="legacy_cars")
*/
class LegacyCar
{
/**
* @Id
* @GeneratedValue
* @Column(name="iCarId", type="integer", nullable=false)
*/
public $_id;
/**
* @ManyToMany(targetEntity="LegacyUser", mappedBy="_cars")
*/
public $_users;
/**
* @Column(name="sDescription", type="string", length=255, unique=true)
*/
public $_description;
function getDescription()
{
return $this->_description;
}
public function addUser(LegacyUser $user) {
$this->_users[] = $user;
}
public function getUsers() {
return $this->_users;
}
}

View File

@ -0,0 +1,80 @@
<?php
namespace Doctrine\Tests\Models\Legacy;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @Entity
* @Table(name="legacy_users")
*/
class LegacyUser
{
/**
* @Id
* @GeneratedValue
* @Column(name="iUserId", type="integer", nullable=false)
*/
public $_id;
/**
* @Column(name="sUsername", type="string", length=255, unique=true)
*/
public $_username;
/**
* @Column(type="string", length=255)
*/
public $_name;
/**
* @OneToMany(targetEntity="LegacyArticle", mappedBy="_user")
*/
public $_articles;
/**
* @OneToMany(targetEntity="LegacyUserReference", mappedBy="_source", cascade={"remove"})
*/
public $_references;
/**
* @ManyToMany(targetEntity="LegacyCar", inversedBy="_users", cascade={"persist", "merge"})
* @JoinTable(name="legace_users_cars",
* joinColumns={@JoinColumn(name="iUserId", referencedColumnName="iUserId")},
* inverseJoinColumns={@JoinColumn(name="iCarId", referencedColumnName="iCarId")}
* )
*/
public $_cars;
public function __construct() {
$this->_articles = new ArrayCollection;
$this->_references = new ArrayCollection;
$this->_cars = new ArrayCollection;
}
public function getId() {
return $this->_id;
}
public function getUsername() {
return $this->_username;
}
public function addArticle(LegacyArticle $article) {
$this->_articles[] = $article;
$article->setAuthor($this);
}
public function addReference($reference)
{
$this->_references[] = $reference;
}
public function references()
{
return $this->_references;
}
public function addCar(LegacyCar $car) {
$this->_cars[] = $car;
$car->addUser($this);
}
public function getCars() {
return $this->_cars;
}
}

View File

@ -0,0 +1,65 @@
<?php
namespace Doctrine\Tests\Models\Legacy;
/**
* @Entity
* @Table(name="legacy_users_reference")
*/
class LegacyUserReference
{
/**
* @Id
* @ManyToOne(targetEntity="LegacyUser", inversedBy="_references")
* @JoinColumn(name="iUserIdSource", referencedColumnName="iUserId")
*/
private $_source;
/**
* @Id
* @ManyToOne(targetEntity="LegacyUser", inversedBy="_references")
* @JoinColumn(name="iUserIdTarget", referencedColumnName="iUserId")
*/
private $_target;
/**
* @column(type="string")
*/
private $_description;
/**
* @column(type="datetime")
*/
private $_created;
public function __construct($source, $target, $description)
{
$source->addReference($this);
$target->addReference($this);
$this->_source = $source;
$this->_target = $target;
$this->_description = $description;
$this->_created = new \DateTime("now");
}
public function source()
{
return $this->_source;
}
public function target()
{
return $this->_target;
}
public function setDescription($desc)
{
$this->_description = $desc;
}
public function getDescription()
{
return $this->_description;
}
}

View File

@ -0,0 +1,148 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
require_once __DIR__ . '/../../../TestInit.php';
/**
* @author asm89
*/
class DDC1301Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
private $userId;
public function setUp()
{
$this->useModelSet('legacy');
parent::setUp();
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\Legacy\LegacyUser');
$class->associationMappings['_articles']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
$class->associationMappings['_references']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
$class->associationMappings['_cars']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
$this->loadFixture();
}
public function tearDown()
{
parent::tearDown();
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\Legacy\LegacyUser');
$class->associationMappings['_articles']['fetch'] = ClassMetadataInfo::FETCH_LAZY;
$class->associationMappings['_references']['fetch'] = ClassMetadataInfo::FETCH_LAZY;
$class->associationMappings['_cars']['fetch'] = ClassMetadataInfo::FETCH_LAZY;
}
public function testCountNotInitializesLegacyCollection()
{
$user = $this->_em->find('Doctrine\Tests\Models\Legacy\LegacyUser', $this->userId);
$queryCount = $this->getCurrentQueryCount();
$this->assertFalse($user->_articles->isInitialized());
$this->assertEquals(2, count($user->_articles));
$this->assertFalse($user->_articles->isInitialized());
foreach ($user->_articles AS $article) { }
$this->assertEquals($queryCount + 2, $this->getCurrentQueryCount(), "Expecting two queries to be fired for count, then iteration.");
}
public function testCountNotInitializesLegacyCollectionWithForeignIdentifier()
{
$user = $this->_em->find('Doctrine\Tests\Models\Legacy\LegacyUser', $this->userId);
$queryCount = $this->getCurrentQueryCount();
$this->assertFalse($user->_references->isInitialized());
$this->assertEquals(2, count($user->_references));
$this->assertFalse($user->_references->isInitialized());
foreach ($user->_references AS $reference) { }
$this->assertEquals($queryCount + 2, $this->getCurrentQueryCount(), "Expecting two queries to be fired for count, then iteration.");
}
public function testCountNotInitializesLegacyManyToManyCollection()
{
$user = $this->_em->find('Doctrine\Tests\Models\Legacy\LegacyUser', $this->userId);
$queryCount = $this->getCurrentQueryCount();
$this->assertFalse($user->_cars->isInitialized());
$this->assertEquals(3, count($user->_cars));
$this->assertFalse($user->_cars->isInitialized());
foreach ($user->_cars AS $reference) { }
$this->assertEquals($queryCount + 2, $this->getCurrentQueryCount(), "Expecting two queries to be fired for count, then iteration.");
}
public function loadFixture()
{
$user1 = new \Doctrine\Tests\Models\Legacy\LegacyUser();
$user1->_username = "beberlei";
$user1->_name = "Benjamin";
$user1->_status = "active";
$user2 = new \Doctrine\Tests\Models\Legacy\LegacyUser();
$user2->_username = "jwage";
$user2->_name = "Jonathan";
$user2->_status = "active";
$user3 = new \Doctrine\Tests\Models\Legacy\LegacyUser();
$user3->_username = "romanb";
$user3->_name = "Roman";
$user3->_status = "active";
$this->_em->persist($user1);
$this->_em->persist($user2);
$this->_em->persist($user3);
$article1 = new \Doctrine\Tests\Models\Legacy\LegacyArticle();
$article1->_topic = "Test";
$article1->_text = "Test";
$article1->setAuthor($user1);
$article2 = new \Doctrine\Tests\Models\Legacy\LegacyArticle();
$article2->_topic = "Test";
$article2->_text = "Test";
$article2->setAuthor($user1);
$this->_em->persist($article1);
$this->_em->persist($article2);
$car1 = new \Doctrine\Tests\Models\Legacy\LegacyCar();
$car1->_description = "Test1";
$car2 = new \Doctrine\Tests\Models\Legacy\LegacyCar();
$car2->_description = "Test2";
$car3 = new \Doctrine\Tests\Models\Legacy\LegacyCar();
$car3->_description = "Test3";
$user1->addCar($car1);
$user1->addCar($car2);
$user1->addCar($car3);
$user2->addCar($car1);
$user3->addCar($car1);
$this->_em->persist($car1);
$this->_em->persist($car2);
$this->_em->persist($car3);
$this->_em->flush();
$detail1 = new \Doctrine\Tests\Models\Legacy\LegacyUserReference($user1, $user2, "foo");
$detail2 = new \Doctrine\Tests\Models\Legacy\LegacyUserReference($user1, $user3, "bar");
$this->_em->persist($detail1);
$this->_em->persist($detail2);
$this->_em->flush();
$this->_em->clear();
$this->userId = $user1->getId();
}
}

View File

@ -105,6 +105,12 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
'Doctrine\Tests\Models\StockExchange\Stock',
'Doctrine\Tests\Models\StockExchange\Market',
),
'legacy' => array(
'Doctrine\Tests\Models\Legacy\LegacyUser',
'Doctrine\Tests\Models\Legacy\LegacyUserReference',
'Doctrine\Tests\Models\Legacy\LegacyArticle',
'Doctrine\Tests\Models\Legacy\LegacyCar',
),
);
protected function useModelSet($setName)
@ -204,6 +210,12 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
$conn->executeUpdate('DELETE FROM exchange_stocks');
$conn->executeUpdate('DELETE FROM exchange_markets');
}
if (isset($this->_usedModelSets['legacy'])) {
$conn->executeUpdate('DELETE FROM legacy_articles');
$conn->executeUpdate('DELETE FROM legacy_cars');
$conn->executeUpdate('DELETE FROM legacy_users');
$conn->executeUpdate('DELETE FROM legacy_users_reference');
}
$this->_em->clear();
}