diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayAgg.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayAgg.php index 34cb73f5..b79f7735 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayAgg.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayAgg.php @@ -4,14 +4,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; -use Doctrine\ORM\Query\Lexer; -use Doctrine\ORM\Query\Parser; -use Doctrine\ORM\Query\SqlWalker; -use Doctrine\ORM\Query\TokenType; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Traits\DistinctableTrait; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Traits\OrderableTrait; -use MartinGeorgiev\Utils\DoctrineOrm; - /** * Implementation of PostgreSQL ARRAY_AGG(). * @@ -20,42 +12,11 @@ * * @author Martin Georgiev */ -class ArrayAgg extends BaseFunction +class ArrayAgg extends BaseAggregateFunction { - use OrderableTrait; - use DistinctableTrait; - protected function customizeFunction(): void { $this->setFunctionPrototype('array_agg(%s%s%s)'); $this->addNodeMapping('StringPrimary'); } - - public function parse(Parser $parser): void - { - $shouldUseLexer = DoctrineOrm::isPre219(); - - $this->customizeFunction(); - - $parser->match($shouldUseLexer ? Lexer::T_IDENTIFIER : TokenType::T_IDENTIFIER); - $parser->match($shouldUseLexer ? Lexer::T_OPEN_PARENTHESIS : TokenType::T_OPEN_PARENTHESIS); - - $this->parseDistinctClause($parser); - $this->expression = $parser->StringPrimary(); - - $this->parseOrderByClause($parser); - - $parser->match($shouldUseLexer ? Lexer::T_CLOSE_PARENTHESIS : TokenType::T_CLOSE_PARENTHESIS); - } - - public function getSql(SqlWalker $sqlWalker): string - { - $dispatched = [ - $this->getOptionalDistinctClause(), - $this->expression->dispatch($sqlWalker), - $this->getOptionalOrderByClause($sqlWalker), - ]; - - return \vsprintf($this->functionPrototype, $dispatched); - } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseAggregateFunction.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseAggregateFunction.php new file mode 100644 index 00000000..a07d2d43 --- /dev/null +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseAggregateFunction.php @@ -0,0 +1,52 @@ + + */ +abstract class BaseAggregateFunction extends BaseFunction +{ + use OrderableTrait; + use DistinctableTrait; + + public function parse(Parser $parser): void + { + $shouldUseLexer = DoctrineOrm::isPre219(); + + $this->customizeFunction(); + + $parser->match($shouldUseLexer ? Lexer::T_IDENTIFIER : TokenType::T_IDENTIFIER); + $parser->match($shouldUseLexer ? Lexer::T_OPEN_PARENTHESIS : TokenType::T_OPEN_PARENTHESIS); + + $this->parseDistinctClause($parser); + $this->expression = $parser->StringPrimary(); + + $this->parseOrderByClause($parser); + + $parser->match($shouldUseLexer ? Lexer::T_CLOSE_PARENTHESIS : TokenType::T_CLOSE_PARENTHESIS); + } + + public function getSql(SqlWalker $sqlWalker): string + { + $dispatched = [ + $this->getOptionalDistinctClause(), + $this->expression->dispatch($sqlWalker), + $this->getOptionalOrderByClause($sqlWalker), + ]; + + return \vsprintf($this->functionPrototype, $dispatched); + } +} diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonAgg.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonAgg.php index bde31498..69f2940a 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonAgg.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonAgg.php @@ -12,11 +12,11 @@ * * @author Martin Georgiev */ -class JsonAgg extends BaseFunction +class JsonAgg extends BaseAggregateFunction { protected function customizeFunction(): void { - $this->setFunctionPrototype('json_agg(%s)'); + $this->setFunctionPrototype('json_agg(%s%s%s)'); $this->addNodeMapping('StringPrimary'); } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbAgg.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbAgg.php index c91ab5c9..dc0ed6af 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbAgg.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbAgg.php @@ -12,11 +12,11 @@ * * @author Martin Georgiev */ -class JsonbAgg extends BaseFunction +class JsonbAgg extends BaseAggregateFunction { protected function customizeFunction(): void { - $this->setFunctionPrototype('jsonb_agg(%s)'); + $this->setFunctionPrototype('jsonb_agg(%s%s%s)'); $this->addNodeMapping('StringPrimary'); } } diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonAggTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonAggTest.php index da11dcef..4a866183 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonAggTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonAggTest.php @@ -19,14 +19,28 @@ protected function getStringFunctions(): array protected function getExpectedSqlStatements(): array { return [ - 'SELECT json_agg(c0_.text1) AS sclr_0 FROM ContainsTexts c0_', + 'basic usage' => 'SELECT json_agg(c0_.text1) AS sclr_0 FROM ContainsTexts c0_', + 'with concatenation' => 'SELECT json_agg(c0_.text1 || c0_.text2) AS sclr_0 FROM ContainsTexts c0_', + 'with DISTINCT' => 'SELECT json_agg(DISTINCT c0_.text1) AS sclr_0 FROM ContainsTexts c0_', + 'with DISTINCT and concatenation' => 'SELECT json_agg(DISTINCT c0_.text1 || c0_.text2) AS sclr_0 FROM ContainsTexts c0_', + 'with ORDER BY' => 'SELECT json_agg(c0_.text1 ORDER BY c0_.text1 ASC) AS sclr_0 FROM ContainsTexts c0_', + 'with ORDER BY DESC' => 'SELECT json_agg(c0_.text1 ORDER BY c0_.text1 DESC) AS sclr_0 FROM ContainsTexts c0_', + 'with DISTINCT and ORDER BY' => 'SELECT json_agg(DISTINCT c0_.text1 ORDER BY c0_.text1 ASC) AS sclr_0 FROM ContainsTexts c0_', + 'with DISTINCT and ORDER BY DESC' => 'SELECT json_agg(DISTINCT c0_.text1 ORDER BY c0_.text1 DESC) AS sclr_0 FROM ContainsTexts c0_', ]; } protected function getDqlStatements(): array { return [ - \sprintf('SELECT JSON_AGG(e.text1) FROM %s e', ContainsTexts::class), + 'basic usage' => \sprintf('SELECT JSON_AGG(e.text1) FROM %s e', ContainsTexts::class), + 'with concatenation' => \sprintf('SELECT JSON_AGG(CONCAT(e.text1, e.text2)) FROM %s e', ContainsTexts::class), + 'with DISTINCT' => \sprintf('SELECT JSON_AGG(DISTINCT e.text1) FROM %s e', ContainsTexts::class), + 'with DISTINCT and concatenation' => \sprintf('SELECT JSON_AGG(DISTINCT CONCAT(e.text1, e.text2)) FROM %s e', ContainsTexts::class), + 'with ORDER BY' => \sprintf('SELECT JSON_AGG(e.text1 ORDER BY e.text1) FROM %s e', ContainsTexts::class), + 'with ORDER BY DESC' => \sprintf('SELECT JSON_AGG(e.text1 ORDER BY e.text1 DESC) FROM %s e', ContainsTexts::class), + 'with DISTINCT and ORDER BY' => \sprintf('SELECT JSON_AGG(DISTINCT e.text1 ORDER BY e.text1) FROM %s e', ContainsTexts::class), + 'with DISTINCT and ORDER BY DESC' => \sprintf('SELECT JSON_AGG(DISTINCT e.text1 ORDER BY e.text1 DESC) FROM %s e', ContainsTexts::class), ]; } } diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbAggTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbAggTest.php index 6fba3b5a..cd166dbc 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbAggTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbAggTest.php @@ -19,14 +19,28 @@ protected function getStringFunctions(): array protected function getExpectedSqlStatements(): array { return [ - 'SELECT jsonb_agg(c0_.text1) AS sclr_0 FROM ContainsTexts c0_', + 'basic usage' => 'SELECT jsonb_agg(c0_.text1) AS sclr_0 FROM ContainsTexts c0_', + 'with concatenation' => 'SELECT jsonb_agg(c0_.text1 || c0_.text2) AS sclr_0 FROM ContainsTexts c0_', + 'with DISTINCT' => 'SELECT jsonb_agg(DISTINCT c0_.text1) AS sclr_0 FROM ContainsTexts c0_', + 'with DISTINCT and concatenation' => 'SELECT jsonb_agg(DISTINCT c0_.text1 || c0_.text2) AS sclr_0 FROM ContainsTexts c0_', + 'with ORDER BY' => 'SELECT jsonb_agg(c0_.text1 ORDER BY c0_.text1 ASC) AS sclr_0 FROM ContainsTexts c0_', + 'with ORDER BY DESC' => 'SELECT jsonb_agg(c0_.text1 ORDER BY c0_.text1 DESC) AS sclr_0 FROM ContainsTexts c0_', + 'with DISTINCT and ORDER BY' => 'SELECT jsonb_agg(DISTINCT c0_.text1 ORDER BY c0_.text1 ASC) AS sclr_0 FROM ContainsTexts c0_', + 'with DISTINCT and ORDER BY DESC' => 'SELECT jsonb_agg(DISTINCT c0_.text1 ORDER BY c0_.text1 DESC) AS sclr_0 FROM ContainsTexts c0_', ]; } protected function getDqlStatements(): array { return [ - \sprintf('SELECT JSONB_AGG(e.text1) FROM %s e', ContainsTexts::class), + 'basic usage' => \sprintf('SELECT JSONB_AGG(e.text1) FROM %s e', ContainsTexts::class), + 'with concatenation' => \sprintf('SELECT JSONB_AGG(CONCAT(e.text1, e.text2)) FROM %s e', ContainsTexts::class), + 'with DISTINCT' => \sprintf('SELECT JSONB_AGG(DISTINCT e.text1) FROM %s e', ContainsTexts::class), + 'with DISTINCT and concatenation' => \sprintf('SELECT JSONB_AGG(DISTINCT CONCAT(e.text1, e.text2)) FROM %s e', ContainsTexts::class), + 'with ORDER BY' => \sprintf('SELECT JSONB_AGG(e.text1 ORDER BY e.text1) FROM %s e', ContainsTexts::class), + 'with ORDER BY DESC' => \sprintf('SELECT JSONB_AGG(e.text1 ORDER BY e.text1 DESC) FROM %s e', ContainsTexts::class), + 'with DISTINCT and ORDER BY' => \sprintf('SELECT JSONB_AGG(DISTINCT e.text1 ORDER BY e.text1) FROM %s e', ContainsTexts::class), + 'with DISTINCT and ORDER BY DESC' => \sprintf('SELECT JSONB_AGG(DISTINCT e.text1 ORDER BY e.text1 DESC) FROM %s e', ContainsTexts::class), ]; } }