Skip to content

Commit 7e6c6e3

Browse files
authored
BAP-20048: DQL cache issue with parameter with dynamic part in DQL (#28363)
- fixing failing tests
1 parent 3bc99fa commit 7e6c6e3

File tree

3 files changed

+75
-2
lines changed

3 files changed

+75
-2
lines changed

src/Oro/Bundle/FilterBundle/Datasource/Orm/OrmFilterDatasourceAdapter.php

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Oro\Bundle\FilterBundle\Datasource\Orm;
44

55
use Doctrine\DBAL\Platforms\MySqlPlatform;
6+
use Doctrine\ORM\Query\Parameter;
67
use Doctrine\ORM\QueryBuilder;
78
use Oro\Bundle\BatchBundle\ORM\QueryBuilder\QueryBuilderTools;
89
use Oro\Bundle\FilterBundle\Datasource\FilterDatasourceAdapterInterface;
@@ -13,6 +14,8 @@
1314
*/
1415
class OrmFilterDatasourceAdapter implements FilterDatasourceAdapterInterface
1516
{
17+
private const GENERATED_PARAMETERS_PREFIX = '_gpnp'; // Generated Parameter Name Prefix
18+
1619
/**
1720
* @var QueryBuilder
1821
*/
@@ -28,6 +31,11 @@ class OrmFilterDatasourceAdapter implements FilterDatasourceAdapterInterface
2831
*/
2932
private $expressionBuilder;
3033

34+
/**
35+
* @var array
36+
*/
37+
private $parameterNames = [];
38+
3139
/**
3240
* @param QueryBuilder $qb
3341
*/
@@ -117,7 +125,37 @@ public function setParameter($key, $value, $type = null)
117125
*/
118126
public function generateParameterName($filterName)
119127
{
120-
return preg_replace('#[^a-z0-9]#i', '', $filterName) . mt_rand();
128+
if (!array_key_exists($filterName, $this->parameterNames)) {
129+
$this->parameterNames[$filterName] = 0;
130+
}
131+
132+
$usedParameterNames = [];
133+
/** @var Parameter $parameter */
134+
foreach ($this->qb->getParameters() as $parameter) {
135+
$usedParameterNames[$parameter->getName()] = true;
136+
}
137+
138+
return $this->generateUniqueParameterName($filterName, $usedParameterNames);
139+
}
140+
141+
/**
142+
* Get parameter name unique for the query.
143+
*
144+
* @param string $filterName
145+
* @param array $usedParameterNames
146+
* @return string
147+
*/
148+
private function generateUniqueParameterName($filterName, array $usedParameterNames)
149+
{
150+
$parameterName = self::GENERATED_PARAMETERS_PREFIX
151+
. preg_replace('#[^a-z0-9]#i', '', $filterName)
152+
. ++$this->parameterNames[$filterName];
153+
154+
if (!empty($usedParameterNames[$parameterName])) {
155+
return $this->generateUniqueParameterName($filterName, $usedParameterNames);
156+
}
157+
158+
return $parameterName;
121159
}
122160

123161
/**
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace Oro\Bundle\FilterBundle\Tests\Unit\Datasource\Orm;
4+
5+
use Doctrine\Common\Collections\ArrayCollection;
6+
use Doctrine\ORM\Query\Parameter;
7+
use Doctrine\ORM\QueryBuilder;
8+
use Oro\Bundle\FilterBundle\Datasource\Orm\OrmFilterDatasourceAdapter;
9+
10+
class OrmFilterDatasourceAdapterTest extends \PHPUnit\Framework\TestCase
11+
{
12+
public function testGenerateParameterName()
13+
{
14+
$parameters = new ArrayCollection([new Parameter('_gpnpint1', 1)]);
15+
16+
$qb = $this->createMock(QueryBuilder::class);
17+
$qb->expects($this->any())
18+
->method('getParameters')
19+
->willReturn($parameters);
20+
21+
$adapter1 = new OrmFilterDatasourceAdapter($qb);
22+
$adapter2 = new OrmFilterDatasourceAdapter($qb);
23+
24+
// Check that counters for the same prefix are increased
25+
$this->assertEquals('_gpnpstring1', $adapter1->generateParameterName('string'));
26+
$this->assertEquals('_gpnpstring2', $adapter1->generateParameterName('string'));
27+
// Check that counters are prefix related
28+
$this->assertEquals('_gpnpdate1', $adapter1->generateParameterName('date'));
29+
// Check that if parameter is present in QB its name will be not generated
30+
$this->assertEquals('_gpnpint2', $adapter1->generateParameterName('int'));
31+
32+
// Check that second adapter use its own counters.
33+
$this->assertEquals('_gpnpstring1', $adapter2->generateParameterName('string'));
34+
}
35+
}

src/Oro/Bundle/SegmentBundle/Tests/Unit/Query/DynamicSegmentQueryBuilderTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ function ($matches) use (&$counter) {
9595
);
9696
$result = preg_replace('/(ts)(\d+)/', 't1', $result);
9797
$this->assertSame(
98-
'SELECT t1.userName, t1.id FROM AcmeBundle:UserEntity t1 WHERE t1.email LIKE :string1',
98+
'SELECT t1.userName, t1.id FROM AcmeBundle:UserEntity t1 WHERE t1.email LIKE :_gpnpstring1',
9999
$result
100100
);
101101
}

0 commit comments

Comments
 (0)