Skip to content

Commit

Permalink
Allow arithmetic expressions within IN operator (#9242)
Browse files Browse the repository at this point in the history
* allow arithmetic expressions within IN operator

Co-authored-by: Artem Stepin <[email protected]>
  • Loading branch information
webda2l and astepin authored Dec 27, 2021
1 parent f1483f8 commit 92ff9c9
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 5 deletions.
2 changes: 1 addition & 1 deletion docs/en/reference/dql-doctrine-query-language.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1724,7 +1724,7 @@ Literal Values
.. code-block:: php
Literal ::= string | char | integer | float | boolean
InParameter ::= Literal | InputParameter
InParameter ::= ArithmeticExpression | InputParameter
Input Parameter
~~~~~~~~~~~~~~~
Expand Down
6 changes: 3 additions & 3 deletions lib/Doctrine/ORM/Query/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -2758,17 +2758,17 @@ public function Literal()
}

/**
* InParameter ::= Literal | InputParameter
* InParameter ::= ArithmeticExpression | InputParameter
*
* @return AST\InputParameter|AST\Literal
* @return AST\InputParameter|AST\ArithmeticExpression
*/
public function InParameter()
{
if ($this->lexer->lookahead['type'] === Lexer::T_INPUT_PARAMETER) {
return $this->InputParameter();
}

return $this->Literal();
return $this->ArithmeticExpression();
}

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/Doctrine/ORM/Query/SqlWalker.php
Original file line number Diff line number Diff line change
Expand Up @@ -2106,7 +2106,7 @@ public function walkInParameter($inParam)
{
return $inParam instanceof AST\InputParameter
? $this->walkInputParameter($inParam)
: $this->walkLiteral($inParam);
: $this->walkArithmeticExpression($inParam);
}

/**
Expand Down
33 changes: 33 additions & 0 deletions tests/Doctrine/Tests/ORM/Functional/QueryDqlFunctionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,39 @@ public function testBitAndComparison(): void
self::assertEquals($result[3][0]['salary'] / 100000 & 2, $result[3]['salary_bit_and']);
}

public function testInArithmeticExpression1(): void
{
$dql = <<<'SQL'
SELECT m, m.name AS m_name
FROM Doctrine\Tests\Models\Company\CompanyManager m
WHERE m.salary IN (800000 / 8, 100000 * 2)
SQL;

$result = $this->_em->createQuery($dql)->getArrayResult();

self::assertCount(2, $result);
self::assertEquals('Roman B.', $result[0]['m_name']);
self::assertEquals('Benjamin E.', $result[1]['m_name']);
}

public function testInArithmeticExpression2(): void
{
$this->_em->getConfiguration()->addCustomStringFunction('FOO', static function ($funcName) {
return new NoOp($funcName); // See Doctrine/Tests/ORM/Functional/CustomFunctionsTest
});

$dql = <<<'SQL'
SELECT m, m.name AS m_name
FROM Doctrine\Tests\Models\Company\CompanyManager m
WHERE m.department IN (FOO('Administration'))
SQL;

$result = $this->_em->createQuery($dql)->getArrayResult();

self::assertCount(1, $result);
self::assertEquals('Jonathan W.', $result[0]['m_name']);
}

protected function generateFixture(): void
{
$manager1 = new CompanyManager();
Expand Down
14 changes: 14 additions & 0 deletions tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,20 @@ public function testInvalidInExpressionWithSingleValuedAssociationPathExpression
);
}

public function testInExpressionWithArithmeticExpression(): void
{
$this->entityManager->getConfiguration()->addCustomStringFunction('FOO', MyAbsFunction::class);

$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u WHERE u.username IN (FOO('Lo'), 'Lo', :name)",
"SELECT f0_.id AS id_0, f0_.username AS username_1 FROM forum_users f0_ WHERE f0_.username IN (ABS('Lo'), 'Lo', ?)"
);
$this->assertSqlGeneration(
'SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u WHERE u.id IN (1 + 1)',
'SELECT f0_.id AS id_0, f0_.username AS username_1 FROM forum_users f0_ WHERE f0_.id IN (1 + 1)'
);
}

public function testSupportsConcatFunctionForMysqlAndPostgresql(): void
{
$connMock = $this->entityManager->getConnection();
Expand Down

0 comments on commit 92ff9c9

Please sign in to comment.