diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php index 4d1bba2fd..a9f411146 100644 --- a/lib/Doctrine/ORM/Query/Parser.php +++ b/lib/Doctrine/ORM/Query/Parser.php @@ -1333,18 +1333,31 @@ class Parser } /** - * OrderByItem ::= (ResultVariable | SingleValuedPathExpression) ["ASC" | "DESC"] + * OrderByItem ::= ( + * SimpleArithmeticExpression | SingleValuedPathExpression | CaseExpression | + * ScalarExpression | AggregateExpression | FunctionDeclaration | ResultVariable + * ) ["ASC" | "DESC"] * * @return \Doctrine\ORM\Query\AST\OrderByItem */ public function OrderByItem() { - // We need to check if we are in a ResultVariable or StateFieldPathExpression + + $this->_lexer->peek(); // lookahead => '.' + $this->_lexer->peek(); // lookahead => token after '.' + $peek = $this->_lexer->peek(); // lookahead => token after the token after the '.' + $this->_lexer->resetPeek(); $glimpse = $this->_lexer->glimpse(); switch (true) { + + case ($this->_isMathOperator($peek)): + $expr = $this->SimpleArithmeticExpression(); + + break; case ($glimpse['type'] === Lexer::T_DOT): $expr = $this->SingleValuedPathExpression(); + break; case ($this->_lexer->lookahead['type'] === Lexer::T_CASE): diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index 1e095ff5a..da7867640 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -780,22 +780,9 @@ class SqlWalker implements TreeWalker public function walkOrderByItem($orderByItem) { $expr = $orderByItem->expression; - - switch (true) { - case ($expr instanceof AST\PathExpression): - case ($expr instanceof AST\AggregateExpression): - case ($expr instanceof AST\Functions\FunctionNode): - case ($expr instanceof AST\SimpleArithmeticExpression): - case ($expr instanceof AST\NullIfExpression): - case ($expr instanceof AST\CoalesceExpression): - case ($expr instanceof AST\SimpleCaseExpression): - case ($expr instanceof AST\GeneralCaseExpression): - $sql = $expr->dispatch($this); - break; - default: - $sql = $this->walkResultVariable($this->_queryComponents[$expr]['token']['value']); - break; - } + $sql = ($expr instanceof AST\Node) + ? $expr->dispatch($this) + : $this->walkResultVariable($this->_queryComponents[$expr]['token']['value']); return $sql . ' ' . strtoupper($orderByItem->type); } diff --git a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php index 314f998b4..b816584dc 100644 --- a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php +++ b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php @@ -1575,28 +1575,24 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase /** * @group DDC-775 */ - public function testOrderByClauseSupportFunctions() + public function testOrderByClauseSupportsFunctions() { $this->assertSqlGeneration( 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY TRIM(u.name)', 'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ ORDER BY TRIM(c0_.name) ASC' ); - $this->assertSqlGeneration( 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY IDENTITY(u.email)', 'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ ORDER BY c0_.email_id ASC' ); - $this->assertSqlGeneration( 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY TRIM(IDENTITY(u.email))', 'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ ORDER BY TRIM(c0_.email_id) ASC' ); - $this->assertSqlGeneration( 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY SUM(u.id)', 'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ ORDER BY SUM(c0_.id) ASC' ); - $this->assertSqlGeneration( 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY SUM(u.id) + COUNT(u.email)', 'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ ORDER BY SUM(c0_.id) + COUNT(c0_.email_id) ASC' @@ -1606,19 +1602,39 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase /** * @group DDC-775 */ - public function testOrderByClauseSupportNullIfAndCoalesce() + public function testOrderByClauseSupportsSimpleArithmeticExpression() { + $this->assertSqlGeneration( + 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY u.id + 1 ', + 'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ ORDER BY c0_.id + 1 ASC' + ); + $this->assertSqlGeneration( + 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY ( ( (u.id + 1) * (u.id - 1) ) / 2)', + 'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ ORDER BY (c0_.id + 1) * (c0_.id - 1) / 2 ASC' + ); + $this->assertSqlGeneration( + 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY ((u.id + 5000) * u.id + 3) ', + 'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ ORDER BY (c0_.id + 5000) * c0_.id + 3 ASC' + ); + $this->assertSqlGeneration( + 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY ((u.id + 5000) * SUM(u.id) + 3) ', + 'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ ORDER BY (c0_.id + 5000) * SUM(c0_.id) + 3 ASC' + ); + } + /** + * @group DDC-775 + */ + public function testOrderByClauseSupportsNullIfAndCoalesce() + { $this->assertSqlGeneration( 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY NULLIF(u.name, u.username)', 'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ ORDER BY NULLIF(c0_.name, c0_.username) ASC' ); - $this->assertSqlGeneration( 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY COALESCE(NULLIF(u.name, u.username), u.id)', 'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ ORDER BY COALESCE(NULLIF(c0_.name, c0_.username), c0_.id) ASC' ); - $this->assertSqlGeneration( 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY CASE u.id WHEN 1 THEN 1 ELSE 0 END', 'SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ ORDER BY CASE c0_.id WHEN 1 THEN 1 ELSE 0 END ASC'