Skip to content

Commit c0b149e

Browse files
committed
Add failing test for failing to update child-parent relation when the child has been prefetched in QB
1 parent 710dde8 commit c0b149e

File tree

3 files changed

+151
-0
lines changed

3 files changed

+151
-0
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\Models\GH7212;
6+
7+
use Doctrine\ORM\Mapping\Column;
8+
use Doctrine\ORM\Mapping\Entity;
9+
use Doctrine\ORM\Mapping\Id;
10+
use Doctrine\ORM\Mapping\ManyToOne;
11+
12+
/** @Entity */
13+
class GH7212Child
14+
{
15+
/**
16+
* @Column(type="integer")
17+
* @Id
18+
* @var int
19+
*/
20+
private $id;
21+
22+
/**
23+
* @ManyToOne(targetEntity=GH7212Parent::class, inversedBy="children")
24+
* @var GH7212Parent|null
25+
*/
26+
private $parent;
27+
28+
public function __construct(int $id, ?GH7212Parent $parent = null)
29+
{
30+
$this->id = $id;
31+
32+
$this->setParent($parent);
33+
}
34+
35+
public function getId(): int
36+
{
37+
return $this->id;
38+
}
39+
40+
public function getParent(): ?GH7212Parent
41+
{
42+
return $this->parent;
43+
}
44+
45+
public function setParent(?GH7212Parent $parent): void
46+
{
47+
$this->parent = $parent;
48+
}
49+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\Models\GH7212;
6+
7+
use Doctrine\Common\Collections\ArrayCollection;
8+
use Doctrine\Common\Collections\Collection;
9+
use Doctrine\ORM\Mapping\Column;
10+
use Doctrine\ORM\Mapping\Entity;
11+
use Doctrine\ORM\Mapping\Id;
12+
use Doctrine\ORM\Mapping\OneToMany;
13+
14+
/** @Entity */
15+
class GH7212Parent
16+
{
17+
/**
18+
* @Column(type="integer")
19+
* @Id
20+
* @var int
21+
*/
22+
private $id;
23+
24+
/**
25+
* @OneToMany(targetEntity=GH7212Child::class, mappedBy="parent", indexBy="id")
26+
* @var Collection<int, GH7212Child>
27+
*/
28+
private $children;
29+
30+
public function __construct(int $id)
31+
{
32+
$this->id = $id;
33+
$this->children = new ArrayCollection();
34+
}
35+
36+
public function getId(): int
37+
{
38+
return $this->id;
39+
}
40+
41+
public function addChild(GH7212Child $child): void
42+
{
43+
$this->children->set($child->getId(), $child);
44+
}
45+
46+
public function removeChild(GH7212Child $child): void
47+
{
48+
$this->children->remove($child->getId());
49+
}
50+
51+
/**
52+
* @return Collection<int, GH7212Child>
53+
*/
54+
public function getChildren(): Collection
55+
{
56+
return $this->children;
57+
}
58+
}

tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,13 @@
1818
use Doctrine\Tests\Models\CMS\CmsGroup;
1919
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
2020
use Doctrine\Tests\Models\CMS\CmsUser;
21+
use Doctrine\Tests\Models\GH7212\GH7212Child;
22+
use Doctrine\Tests\Models\GH7212\GH7212Parent;
2123
use Doctrine\Tests\OrmFunctionalTestCase;
2224
use InvalidArgumentException;
2325
use RuntimeException;
2426

27+
use function assert;
2528
use function get_class;
2629

2730
class BasicFunctionalTest extends OrmFunctionalTestCase
@@ -1355,4 +1358,45 @@ public function testItThrowsWhenReferenceUsesIdAssignedByDatabase(): void
13551358
// post insert IDs will be assigned during flush
13561359
$this->_em->flush();
13571360
}
1361+
1362+
public function testIndexedRelationUpdatesWhenSelectedUsingLeftJoin(): void
1363+
{
1364+
$this->_schemaTool->createSchema(
1365+
[
1366+
$this->_em->getClassMetadata(GH7212Parent::class),
1367+
$this->_em->getClassMetadata(GH7212Child::class),
1368+
]
1369+
);
1370+
1371+
$parent = new GH7212Parent(1);
1372+
$child = new GH7212Child(1, $parent);
1373+
1374+
$this->_em->persist($parent);
1375+
$this->_em->persist($child);
1376+
1377+
$this->_em->flush();
1378+
$this->_em->clear();
1379+
1380+
$parent = $this->_em->createQueryBuilder()
1381+
->select('p, c')
1382+
->from(GH7212Parent::class, 'p')
1383+
// Prefetching Child relation using left join
1384+
->leftJoin('p.children', 'c')
1385+
->getQuery()
1386+
->getSingleResult();
1387+
assert($parent instanceof GH7212Parent);
1388+
1389+
$children = $parent->getChildren();
1390+
foreach ($children as $child) {
1391+
$child->setParent(null);
1392+
$parent->removeChild($child);
1393+
}
1394+
1395+
$this->_em->flush();
1396+
1397+
$childrenRows = $this->_em->getConnection()->fetchAllAssociative('SELECT * FROM GH7212Child');
1398+
$this->assertCount(1, $childrenRows);
1399+
$this->assertSame('1', $childrenRows[0]['id']);
1400+
$this->assertNull($childrenRows[0]['parent_id']);
1401+
}
13581402
}

0 commit comments

Comments
 (0)