From c1df8084a63fd7c83bd531950def97f5f5bebefa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 9 Nov 2022 15:48:20 +0100 Subject: [PATCH] DX: Add DQL function LEAST and GREATEST --- .../ChillMainExtension.php | 4 ++ .../ChillMainBundle/Doctrine/DQL/Greatest.php | 57 +++++++++++++++++++ .../ChillMainBundle/Doctrine/DQL/Least.php | 57 +++++++++++++++++++ .../Tests/Doctrine/DQL/GreatestTest.php | 48 ++++++++++++++++ .../Tests/Doctrine/DQL/LeastTest.php | 48 ++++++++++++++++ 5 files changed, 214 insertions(+) create mode 100644 src/Bundle/ChillMainBundle/Doctrine/DQL/Greatest.php create mode 100644 src/Bundle/ChillMainBundle/Doctrine/DQL/Least.php create mode 100644 src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/GreatestTest.php create mode 100644 src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/LeastTest.php diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php index 7c63263ba..db54150ca 100644 --- a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php +++ b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php @@ -25,10 +25,12 @@ use Chill\MainBundle\DependencyInjection\Widget\Factory\WidgetFactoryInterface; use Chill\MainBundle\Doctrine\DQL\Age; use Chill\MainBundle\Doctrine\DQL\Extract; use Chill\MainBundle\Doctrine\DQL\GetJsonFieldByKey; +use Chill\MainBundle\Doctrine\DQL\Greatest; use Chill\MainBundle\Doctrine\DQL\JsonAggregate; use Chill\MainBundle\Doctrine\DQL\JsonbArrayLength; use Chill\MainBundle\Doctrine\DQL\JsonbExistsInArray; use Chill\MainBundle\Doctrine\DQL\JsonExtract; +use Chill\MainBundle\Doctrine\DQL\Least; use Chill\MainBundle\Doctrine\DQL\OverlapsI; use Chill\MainBundle\Doctrine\DQL\Replace; use Chill\MainBundle\Doctrine\DQL\Similarity; @@ -246,6 +248,8 @@ class ChillMainExtension extends Extension implements 'JSONB_ARRAY_LENGTH' => JsonbArrayLength::class, 'ST_X' => STX::class, 'ST_Y' => STY::class, + 'GREATEST' => Greatest::class, + 'LEAST' => LEAST::class, ], 'datetime_functions' => [ 'EXTRACT' => Extract::class, diff --git a/src/Bundle/ChillMainBundle/Doctrine/DQL/Greatest.php b/src/Bundle/ChillMainBundle/Doctrine/DQL/Greatest.php new file mode 100644 index 000000000..b9ca9c4b6 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Doctrine/DQL/Greatest.php @@ -0,0 +1,57 @@ +dispatch($sqlWalker); + }, $this->exprs)) . ')'; + } + + public function parse(Parser $parser) + { + $this->exprs = []; + + $lexer = $parser->getLexer(); + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + $this->exprs[] = $parser->ArithmeticPrimary(); + + while (Lexer::T_COMMA === $lexer->lookahead['type']) { + $parser->match(Lexer::T_COMMA); + $this->exprs[] = $parser->ArithmeticPrimary(); + } + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/src/Bundle/ChillMainBundle/Doctrine/DQL/Least.php b/src/Bundle/ChillMainBundle/Doctrine/DQL/Least.php new file mode 100644 index 000000000..0c8a1b17d --- /dev/null +++ b/src/Bundle/ChillMainBundle/Doctrine/DQL/Least.php @@ -0,0 +1,57 @@ +dispatch($sqlWalker); + }, $this->exprs)) . ')'; + } + + public function parse(Parser $parser) + { + $this->exprs = []; + + $lexer = $parser->getLexer(); + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + $this->exprs[] = $parser->ArithmeticPrimary(); + + while (Lexer::T_COMMA === $lexer->lookahead['type']) { + $parser->match(Lexer::T_COMMA); + $this->exprs[] = $parser->ArithmeticPrimary(); + } + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/GreatestTest.php b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/GreatestTest.php new file mode 100644 index 000000000..c11061287 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/GreatestTest.php @@ -0,0 +1,48 @@ +entityManager = self::$container->get(EntityManagerInterface::class); + } + + public function testGreatestInDQL() + { + $dql = 'SELECT GREATEST(a.validFrom, a.validTo, :now) AS g FROM ' . Address::class . ' a WHERE a.validTo < :now and a.validFrom < :now'; + + $actual = $this->entityManager + ->createQuery($dql) + ->setParameter('now', $now = new DateTimeImmutable('now'), Types::DATE_IMMUTABLE) + ->setMaxResults(3) + ->getResult(); + + $this->assertIsArray($actual); + $this->assertEquals($now->format('Y-m-d'), $actual[0]['g']); + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/LeastTest.php b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/LeastTest.php new file mode 100644 index 000000000..1e5be8e24 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/LeastTest.php @@ -0,0 +1,48 @@ +entityManager = self::$container->get(EntityManagerInterface::class); + } + + public function testGreatestInDQL() + { + $dql = 'SELECT LEAST(a.validFrom, a.validTo, :now) AS g FROM ' . Address::class . ' a WHERE a.validTo < :now and a.validFrom < :now'; + + $actual = $this->entityManager + ->createQuery($dql) + ->setParameter('now', $now = new DateTimeImmutable('now'), Types::DATE_IMMUTABLE) + ->setMaxResults(3) + ->getResult(); + + $this->assertIsArray($actual); + $this->assertNotEquals($now->format('Y-m-d'), $actual[0]['g']); + } +}