Skip to content

Commit 6307b4f

Browse files
authored
Merge pull request doctrine#8012 from sgehrig/bug/doctrine#8011-ordering-with-arithmetic-expression
Bug/doctrine#8011 ordering with arithmetic expression
2 parents 5d21bb1 + 067ad51 commit 6307b4f

File tree

2 files changed

+239
-1
lines changed

2 files changed

+239
-1
lines changed

src/Query/Parser.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1554,7 +1554,7 @@ public function OrderByItem()
15541554

15551555
assert($this->lexer->lookahead !== null);
15561556
switch (true) {
1557-
case $this->isMathOperator($peek):
1557+
case $this->isMathOperator($peek) || $this->isMathOperator($glimpse):
15581558
$expr = $this->SimpleArithmeticExpression();
15591559
break;
15601560

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\ORM\Functional;
6+
7+
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
8+
use Doctrine\Tests\Models\Company\CompanyEmployee;
9+
use Doctrine\Tests\OrmFunctionalTestCase;
10+
11+
use function count;
12+
13+
/**
14+
* Functional tests for ordering with arithmetic expression.
15+
*
16+
* @group GH8011
17+
*/
18+
class GH8011Test extends OrmFunctionalTestCase
19+
{
20+
protected function setUp(): void
21+
{
22+
$this->useModelSet('company');
23+
24+
parent::setUp();
25+
26+
$this->generateFixture();
27+
}
28+
29+
private function skipIfPostgres(string $test): void
30+
{
31+
$platform = $this->_em->getConnection()->getDatabasePlatform();
32+
if ($platform instanceof PostgreSQLPlatform) {
33+
self::markTestSkipped(
34+
'The ' . $test . ' test does not work on postgresql (see https://github.com/doctrine/orm/pull/8012).'
35+
);
36+
}
37+
}
38+
39+
public function testOrderWithArithmeticExpressionWithSingleValuedPathExpression(): void
40+
{
41+
$dql = 'SELECT p ' .
42+
'FROM Doctrine\Tests\Models\Company\CompanyEmployee p ' .
43+
'ORDER BY p.id + p.id ASC';
44+
45+
/** @var CompanyEmployee[] $result */
46+
$result = $this->_em->createQuery($dql)->getResult();
47+
48+
$this->assertEquals(2, count($result));
49+
$this->assertEquals('Benjamin E.', $result[0]->getName());
50+
$this->assertEquals('Guilherme B.', $result[1]->getName());
51+
}
52+
53+
public function testOrderWithArithmeticExpressionWithLiteralAndSingleValuedPathExpression(): void
54+
{
55+
$dql = 'SELECT p ' .
56+
'FROM Doctrine\Tests\Models\Company\CompanyEmployee p ' .
57+
'ORDER BY 1 + p.id ASC';
58+
59+
/** @var CompanyEmployee[] $result */
60+
$result = $this->_em->createQuery($dql)->getResult();
61+
62+
$this->assertEquals(2, count($result));
63+
$this->assertEquals('Benjamin E.', $result[0]->getName());
64+
$this->assertEquals('Guilherme B.', $result[1]->getName());
65+
}
66+
67+
public function testOrderWithArithmeticExpressionWithLiteralAndSingleValuedPathExpression2(): void
68+
{
69+
$dql = 'SELECT p ' .
70+
'FROM Doctrine\Tests\Models\Company\CompanyEmployee p ' .
71+
'ORDER BY ((1 + p.id)) ASC';
72+
73+
/** @var CompanyEmployee[] $result */
74+
$result = $this->_em->createQuery($dql)->getResult();
75+
76+
$this->assertEquals(2, count($result));
77+
$this->assertEquals('Benjamin E.', $result[0]->getName());
78+
$this->assertEquals('Guilherme B.', $result[1]->getName());
79+
}
80+
81+
public function testOrderWithArithmeticExpressionWithSingleValuedPathExpressionAndLiteral(): void
82+
{
83+
$dql = 'SELECT p ' .
84+
'FROM Doctrine\Tests\Models\Company\CompanyEmployee p ' .
85+
'ORDER BY p.id + 1 ASC';
86+
87+
/** @var CompanyEmployee[] $result */
88+
$result = $this->_em->createQuery($dql)->getResult();
89+
90+
$this->assertEquals(2, count($result));
91+
$this->assertEquals('Benjamin E.', $result[0]->getName());
92+
$this->assertEquals('Guilherme B.', $result[1]->getName());
93+
}
94+
95+
public function testOrderWithArithmeticExpressionWithResultVariableAndLiteral(): void
96+
{
97+
$this->skipIfPostgres(__FUNCTION__);
98+
99+
$dql = 'SELECT p, p.salary AS HIDDEN s ' .
100+
'FROM Doctrine\Tests\Models\Company\CompanyEmployee p ' .
101+
'ORDER BY s + 1 DESC';
102+
103+
/** @var CompanyEmployee[] $result */
104+
$result = $this->_em->createQuery($dql)->getResult();
105+
106+
$this->assertEquals(2, count($result));
107+
$this->assertEquals('Guilherme B.', $result[0]->getName());
108+
$this->assertEquals('Benjamin E.', $result[1]->getName());
109+
}
110+
111+
public function testOrderWithArithmeticExpressionWithResultVariableAndLiteral2(): void
112+
{
113+
$this->skipIfPostgres(__FUNCTION__);
114+
115+
$dql = 'SELECT p, p.salary AS HIDDEN s ' .
116+
'FROM Doctrine\Tests\Models\Company\CompanyEmployee p ' .
117+
'ORDER BY ((s + 1)) DESC';
118+
119+
/** @var CompanyEmployee[] $result */
120+
$result = $this->_em->createQuery($dql)->getResult();
121+
122+
$this->assertEquals(2, count($result));
123+
$this->assertEquals('Guilherme B.', $result[0]->getName());
124+
$this->assertEquals('Benjamin E.', $result[1]->getName());
125+
}
126+
127+
public function testOrderWithArithmeticExpressionWithLiteralAndResultVariable(): void
128+
{
129+
$this->skipIfPostgres(__FUNCTION__);
130+
131+
$dql = 'SELECT p, p.salary AS HIDDEN s ' .
132+
'FROM Doctrine\Tests\Models\Company\CompanyEmployee p ' .
133+
'ORDER BY 1 + s DESC';
134+
135+
/** @var CompanyEmployee[] $result */
136+
$result = $this->_em->createQuery($dql)->getResult();
137+
138+
$this->assertEquals(2, count($result));
139+
$this->assertEquals('Guilherme B.', $result[0]->getName());
140+
$this->assertEquals('Benjamin E.', $result[1]->getName());
141+
}
142+
143+
public function testOrderWithArithmeticExpressionWithLiteralAndResultVariable2(): void
144+
{
145+
$this->skipIfPostgres(__FUNCTION__);
146+
147+
$dql = 'SELECT p, p.salary AS HIDDEN s ' .
148+
'FROM Doctrine\Tests\Models\Company\CompanyEmployee p ' .
149+
'ORDER BY ((1 + s)) DESC';
150+
151+
/** @var CompanyEmployee[] $result */
152+
$result = $this->_em->createQuery($dql)->getResult();
153+
154+
$this->assertEquals(2, count($result));
155+
$this->assertEquals('Guilherme B.', $result[0]->getName());
156+
$this->assertEquals('Benjamin E.', $result[1]->getName());
157+
}
158+
159+
public function testOrderWithArithmeticExpressionWithResultVariableAndSingleValuedPathExpression(): void
160+
{
161+
$this->skipIfPostgres(__FUNCTION__);
162+
163+
$dql = 'SELECT p, p.salary AS HIDDEN s ' .
164+
'FROM Doctrine\Tests\Models\Company\CompanyEmployee p ' .
165+
'ORDER BY s + p.id DESC';
166+
167+
/** @var CompanyEmployee[] $result */
168+
$result = $this->_em->createQuery($dql)->getResult();
169+
170+
$this->assertEquals(2, count($result));
171+
$this->assertEquals('Guilherme B.', $result[0]->getName());
172+
$this->assertEquals('Benjamin E.', $result[1]->getName());
173+
}
174+
175+
public function testOrderWithArithmeticExpressionWithResultVariableAndSingleValuedPathExpression2(): void
176+
{
177+
$this->skipIfPostgres(__FUNCTION__);
178+
179+
$dql = 'SELECT p, p.salary AS HIDDEN s ' .
180+
'FROM Doctrine\Tests\Models\Company\CompanyEmployee p ' .
181+
'ORDER BY ((s + p.id)) DESC';
182+
183+
/** @var CompanyEmployee[] $result */
184+
$result = $this->_em->createQuery($dql)->getResult();
185+
186+
$this->assertEquals(2, count($result));
187+
$this->assertEquals('Guilherme B.', $result[0]->getName());
188+
$this->assertEquals('Benjamin E.', $result[1]->getName());
189+
}
190+
191+
public function testOrderWithArithmeticExpressionWithSingleValuedPathExpressionAndResultVariable(): void
192+
{
193+
$this->skipIfPostgres(__FUNCTION__);
194+
195+
$dql = 'SELECT p, p.salary AS HIDDEN s ' .
196+
'FROM Doctrine\Tests\Models\Company\CompanyEmployee p ' .
197+
'ORDER BY p.id + s DESC';
198+
199+
/** @var CompanyEmployee[] $result */
200+
$result = $this->_em->createQuery($dql)->getResult();
201+
202+
$this->assertEquals(2, count($result));
203+
$this->assertEquals('Guilherme B.', $result[0]->getName());
204+
$this->assertEquals('Benjamin E.', $result[1]->getName());
205+
}
206+
207+
public function testOrderWithArithmeticExpressionWithLiteralAndResultVariableUsingHiddenResultVariable(): void
208+
{
209+
$dql = 'SELECT p, 1 + p.salary AS HIDDEN _order ' .
210+
'FROM Doctrine\Tests\Models\Company\CompanyEmployee p ' .
211+
'ORDER BY _order DESC';
212+
213+
/** @var CompanyEmployee[] $result */
214+
$result = $this->_em->createQuery($dql)->getResult();
215+
216+
$this->assertEquals(2, count($result));
217+
$this->assertEquals('Guilherme B.', $result[0]->getName());
218+
$this->assertEquals('Benjamin E.', $result[1]->getName());
219+
}
220+
221+
public function generateFixture(): void
222+
{
223+
$person1 = new CompanyEmployee();
224+
$person1->setName('Benjamin E.');
225+
$person1->setDepartment('IT');
226+
$person1->setSalary(200000);
227+
228+
$person2 = new CompanyEmployee();
229+
$person2->setName('Guilherme B.');
230+
$person2->setDepartment('IT2');
231+
$person2->setSalary(400000);
232+
233+
$this->_em->persist($person1);
234+
$this->_em->persist($person2);
235+
$this->_em->flush();
236+
$this->_em->clear();
237+
}
238+
}

0 commit comments

Comments
 (0)