Skip to content

Commit

Permalink
Add failing test for failing to update child-parent relation when the…
Browse files Browse the repository at this point in the history
… child has been prefetched in QB
  • Loading branch information
simPod committed Feb 23, 2025
1 parent 36bef3f commit 9df2bba
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 0 deletions.
42 changes: 42 additions & 0 deletions tests/Tests/Models/GH7212/GH7212Child.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace Doctrine\Tests\Models\GH7212;

use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
class GH7212Child
{
/** @var int */
#[ORM\Column(type: 'integer')]
#[ORM\Id]
private $id;

/** @var GH7212Parent|null */
#[ORM\ManyToOne(targetEntity: GH7212Parent::class, inversedBy: 'children')]
private $parent;

public function __construct(int $id, GH7212Parent|null $parent = null)
{
$this->id = $id;

$this->setParent($parent);
}

public function getId(): int
{
return $this->id;
}

public function getParent(): GH7212Parent|null
{
return $this->parent;
}

public function setParent(GH7212Parent|null $parent): void
{
$this->parent = $parent;
}
}
52 changes: 52 additions & 0 deletions tests/Tests/Models/GH7212/GH7212Parent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace Doctrine\Tests\Models\GH7212;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\OneToMany;

#[ORM\Entity]
class GH7212Parent
{
/** @var int */
#[Id]
#[Column(type: 'integer')]
private $id;

/** @var Collection<int, GH7212Child> */
#[OneToMany(targetEntity: GH7212Child::class, mappedBy: 'parent', indexBy: 'id')]
private $children;

public function __construct(int $id)
{
$this->id = $id;
$this->children = new ArrayCollection();
}

public function getId(): int
{
return $this->id;
}

public function addChild(GH7212Child $child): void
{
$this->children->set($child->getId(), $child);
}

public function removeChild(GH7212Child $child): void
{
$this->children->remove($child->getId());
}

/** @return Collection<int, GH7212Child> */
public function getChildren(): Collection
{
return $this->children;
}
}
45 changes: 45 additions & 0 deletions tests/Tests/ORM/Functional/BasicFunctionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@
use Doctrine\Tests\Models\CMS\CmsGroup;
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\Models\GH7212\GH7212Child;
use Doctrine\Tests\Models\GH7212\GH7212Parent;
use Doctrine\Tests\OrmFunctionalTestCase;
use InvalidArgumentException;
use PHPUnit\Framework\Attributes\Group;

use function assert;

class BasicFunctionalTest extends OrmFunctionalTestCase
{
protected function setUp(): void
Expand Down Expand Up @@ -1082,4 +1086,45 @@ public function testItThrowsWhenReferenceUsesIdAssignedByDatabase(): void
// post insert IDs will be assigned during flush
$this->_em->flush();
}

public function testIndexedRelationUpdatesWhenSelectedUsingLeftJoin(): void
{
$this->_schemaTool->createSchema(
[
$this->_em->getClassMetadata(GH7212Parent::class),
$this->_em->getClassMetadata(GH7212Child::class),
],
);

$parent = new GH7212Parent(1);
$child = new GH7212Child(1, $parent);

$this->_em->persist($parent);
$this->_em->persist($child);

$this->_em->flush();
$this->_em->clear();

$parent = $this->_em->createQueryBuilder()
->select('p, c')
->from(GH7212Parent::class, 'p')
// Prefetching Child relation using left join
->leftJoin('p.children', 'c')
->getQuery()
->getSingleResult();
assert($parent instanceof GH7212Parent);

$children = $parent->getChildren();
foreach ($children as $child) {
$child->setParent(null);
$parent->removeChild($child);
}

$this->_em->flush();

$childrenRows = $this->_em->getConnection()->fetchAllAssociative('SELECT * FROM GH7212Child');
$this->assertCount(1, $childrenRows);
$this->assertSame(1, $childrenRows[0]['id']);
$this->assertNull($childrenRows[0]['parent_id']);
}
}

0 comments on commit 9df2bba

Please sign in to comment.