Skip to content

Commit e172b3b

Browse files
committed
#11931 Bug when change sql filter [Related issue #11694]
This fix takes into account the invalidation of the filter sql for SingleTablePersister and JoinedSubclassPersister
1 parent c9c6e8d commit e172b3b

File tree

16 files changed

+448
-19
lines changed

16 files changed

+448
-19
lines changed

src/Persisters/Entity/BasicEntityPersister.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,16 @@ public function __construct(EntityManagerInterface $em, ClassMetadata $class)
226226
);
227227
}
228228

229+
final protected function isFilterHashUpToDate(): bool
230+
{
231+
return $this->filterHash === $this->em->getFilters()->getHash();
232+
}
233+
234+
final protected function updateFilterHash(): void
235+
{
236+
$this->filterHash = $this->em->getFilters()->getHash();
237+
}
238+
229239
/**
230240
* {@inheritDoc}
231241
*/
@@ -1274,7 +1284,7 @@ final protected function getOrderBySQL(array $orderBy, string $baseTableAlias):
12741284
*/
12751285
protected function getSelectColumnsSQL()
12761286
{
1277-
if ($this->currentPersisterContext->selectColumnListSql !== null && $this->filterHash === $this->em->getFilters()->getHash()) {
1287+
if ($this->currentPersisterContext->selectColumnListSql !== null && $this->isFilterHashUpToDate()) {
12781288
return $this->currentPersisterContext->selectColumnListSql;
12791289
}
12801290

@@ -1387,7 +1397,7 @@ protected function getSelectColumnsSQL()
13871397
}
13881398

13891399
$this->currentPersisterContext->selectColumnListSql = implode(', ', $columnList);
1390-
$this->filterHash = $this->em->getFilters()->getHash();
1400+
$this->updateFilterHash();
13911401

13921402
return $this->currentPersisterContext->selectColumnListSql;
13931403
}

src/Persisters/Entity/JoinedSubclassPersister.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ protected function getLockTablesSql($lockMode)
404404
protected function getSelectColumnsSQL()
405405
{
406406
// Create the column list fragment only once
407-
if ($this->currentPersisterContext->selectColumnListSql !== null) {
407+
if ($this->currentPersisterContext->selectColumnListSql !== null && $this->isFilterHashUpToDate()) {
408408
return $this->currentPersisterContext->selectColumnListSql;
409409
}
410410

@@ -495,6 +495,7 @@ protected function getSelectColumnsSQL()
495495
}
496496

497497
$this->currentPersisterContext->selectColumnListSql = implode(', ', $columnList);
498+
$this->updateFilterHash();
498499

499500
return $this->currentPersisterContext->selectColumnListSql;
500501
}

src/Persisters/Entity/SingleTablePersister.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ protected function getDiscriminatorColumnTableName()
3838
*/
3939
protected function getSelectColumnsSQL()
4040
{
41-
if ($this->currentPersisterContext->selectColumnListSql !== null) {
41+
if ($this->currentPersisterContext->selectColumnListSql !== null && $this->isFilterHashUpToDate()) {
4242
return $this->currentPersisterContext->selectColumnListSql;
4343
}
4444

@@ -92,6 +92,7 @@ protected function getSelectColumnsSQL()
9292
}
9393

9494
$this->currentPersisterContext->selectColumnListSql = implode(', ', $columnList);
95+
$this->updateFilterHash();
9596

9697
return $this->currentPersisterContext->selectColumnListSql;
9798
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\ORM\Functional\Ticket\SwitchContextWithFilter;
6+
7+
use Doctrine\Tests\OrmFunctionalTestCase;
8+
9+
use function sprintf;
10+
use function str_replace;
11+
12+
abstract class AbstractTest extends OrmFunctionalTestCase
13+
{
14+
protected function generateMessage(string $message): string
15+
{
16+
$log = $this->getLastLoggedQuery();
17+
18+
return sprintf("%s\nSQL: %s", $message, str_replace(['?'], (array) $log['params'], $log['sql']));
19+
}
20+
21+
/**
22+
* @param object ...$entities
23+
*/
24+
protected function clearCachedData(...$entities): void
25+
{
26+
foreach ($entities as $entity) {
27+
$this->_em->refresh($entity);
28+
}
29+
}
30+
31+
/**
32+
* @param object ...$entities
33+
*/
34+
protected function persistFlushClear(...$entities): void
35+
{
36+
foreach ($entities as $entity) {
37+
$this->_em->persist($entity);
38+
}
39+
40+
$this->_em->flush();
41+
$this->_em->clear();
42+
}
43+
}

tests/Tests/ORM/Functional/Ticket/SwitchContextWithFilter/ChangeFiltersTest.php

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
44

55
namespace Doctrine\Tests\ORM\Functional\Ticket\SwitchContextWithFilter;
66

7-
use Doctrine\Tests\OrmFunctionalTestCase;
7+
use Doctrine\Tests\ORM\Functional\Ticket\SwitchContextWithFilter\Entity\Order;
8+
use Doctrine\Tests\ORM\Functional\Ticket\SwitchContextWithFilter\Entity\User;
9+
use Doctrine\Tests\ORM\Functional\Ticket\SwitchContextWithFilter\SQLFilter\CompanySQLFilter;
810

9-
use function sprintf;
10-
use function str_replace;
11-
12-
final class ChangeFiltersTest extends OrmFunctionalTestCase
11+
final class ChangeFiltersTest extends AbstractTest
1312
{
1413
private const COMPANY_A = 'A';
1514
private const COMPANY_B = 'B';
@@ -132,11 +131,4 @@ public function testUseQueryBuilder(): void
132131
self::assertInstanceOf(User::class, $order->user);
133132
self::assertEquals($companyB['userId'], $order->user->id);
134133
}
135-
136-
private function generateMessage(string $message): string
137-
{
138-
$log = $this->getLastLoggedQuery();
139-
140-
return sprintf("%s\nSQL: %s", $message, str_replace(['?'], (array) $log['params'], $log['sql']));
141-
}
142134
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\ORM\Functional\Ticket\SwitchContextWithFilter\Entity;
6+
7+
use Doctrine\ORM\Mapping as ORM;
8+
9+
/**
10+
* @ORM\Entity()
11+
*/
12+
class Insurance
13+
{
14+
/**
15+
* @ORM\Id
16+
* @ORM\GeneratedValue
17+
* @ORM\Column(type="integer")
18+
*
19+
* @var int
20+
*/
21+
public $id;
22+
23+
/**
24+
* @ORM\Column(type="string")
25+
*
26+
* @var string
27+
*/
28+
public $name;
29+
30+
/**
31+
* @ORM\ManyToOne(targetEntity=Practice::class)
32+
*
33+
* @var Practice
34+
*/
35+
public $practice;
36+
37+
public function __construct(Practice $practice, string $name)
38+
{
39+
$this->practice = $practice;
40+
$this->name = $name;
41+
}
42+
}

tests/Tests/ORM/Functional/Ticket/SwitchContextWithFilter/Order.php renamed to tests/Tests/ORM/Functional/Ticket/SwitchContextWithFilter/Entity/Order.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace Doctrine\Tests\ORM\Functional\Ticket\SwitchContextWithFilter;
5+
namespace Doctrine\Tests\ORM\Functional\Ticket\SwitchContextWithFilter\Entity;
66

77
use Doctrine\ORM\Mapping as ORM;
88

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\ORM\Functional\Ticket\SwitchContextWithFilter\Entity;
6+
7+
use Doctrine\Common\Collections\ArrayCollection;
8+
use Doctrine\Common\Collections\Collection;
9+
use Doctrine\ORM\Mapping as ORM;
10+
11+
/**
12+
* @ORM\Entity()
13+
*/
14+
class Patient
15+
{
16+
/**
17+
* @ORM\Id
18+
* @ORM\GeneratedValue
19+
* @ORM\Column(type="integer")
20+
*
21+
* @var int
22+
*/
23+
public $id;
24+
25+
/**
26+
* @ORM\Column(type="string")
27+
*
28+
* @var string
29+
*/
30+
public $name;
31+
32+
/**
33+
* @ORM\OneToMany(targetEntity=PatientInsurance::class, mappedBy="patient", fetch="LAZY", cascade={"persist"})
34+
*
35+
* @var Collection<int, PatientInsurance>
36+
*/
37+
public $insurances;
38+
39+
public function __construct(string $name)
40+
{
41+
$this->name = $name;
42+
$this->insurances = new ArrayCollection();
43+
}
44+
45+
/**
46+
* @return Collection<PrimaryPatInsurance>
47+
*/
48+
public function getPrimaryInsurances(): Collection
49+
{
50+
return $this->insurances->filter(static function (PatientInsurance $insurances) {
51+
return $insurances instanceof PrimaryPatInsurance;
52+
});
53+
}
54+
55+
/**
56+
* @return Collection<SecondaryPatInsurance>
57+
*/
58+
public function getSecondaryInsurances(): Collection
59+
{
60+
return $this->insurances->filter(static function (PatientInsurance $insurances) {
61+
return $insurances instanceof SecondaryPatInsurance;
62+
});
63+
}
64+
65+
public function addPrimaryInsurance(Insurance $insurance): void
66+
{
67+
$this->insurances[] = new PrimaryPatInsurance($this, $insurance);
68+
}
69+
70+
public function addSecondaryInsurance(Insurance $insurance): void
71+
{
72+
$this->insurances[] = new SecondaryPatInsurance($this, $insurance);
73+
}
74+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\ORM\Functional\Ticket\SwitchContextWithFilter\Entity;
6+
7+
use Doctrine\ORM\Mapping as ORM;
8+
9+
/**
10+
* @ORM\Entity()
11+
* @ORM\InheritanceType("SINGLE_TABLE")
12+
* @ORM\DiscriminatorMap({"primary": PrimaryPatInsurance::class, "secondary": SecondaryPatInsurance::class})
13+
* @ORM\DiscriminatorColumn(name="type", type="string")
14+
*/
15+
abstract class PatientInsurance
16+
{
17+
/**
18+
* @ORM\Id
19+
* @ORM\GeneratedValue
20+
* @ORM\Column(type="integer")
21+
*
22+
* @var int
23+
*/
24+
public $id;
25+
26+
/**
27+
* @ORM\ManyToOne(targetEntity=Insurance::class, fetch="EAGER", cascade={"persist"})
28+
* @ORM\JoinColumn(referencedColumnName="id", nullable=false)
29+
*
30+
* @var Insurance
31+
*/
32+
public $insurance;
33+
34+
/**
35+
* @ORM\ManyToOne(targetEntity=Patient::class, inversedBy="insurances")
36+
*
37+
* @var Patient
38+
*/
39+
public $patient;
40+
41+
public function __construct(Patient $patient, Insurance $insurance)
42+
{
43+
$this->patient = $patient;
44+
$this->insurance = $insurance;
45+
}
46+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\ORM\Functional\Ticket\SwitchContextWithFilter\Entity;
6+
7+
use Doctrine\ORM\Mapping as ORM;
8+
9+
/**
10+
* @ORM\Entity
11+
*/
12+
class Practice
13+
{
14+
/**
15+
* @ORM\Id
16+
* @ORM\GeneratedValue
17+
* @ORM\Column(type="integer")
18+
*
19+
* @var int
20+
*/
21+
public $id;
22+
23+
/**
24+
* @ORM\Column(type="string")
25+
*
26+
* @var string
27+
*/
28+
public $name;
29+
30+
public function __construct(string $name)
31+
{
32+
$this->name = $name;
33+
}
34+
}

0 commit comments

Comments
 (0)