From a3f95d919bfa52550b271486cd6e256e6c91d356 Mon Sep 17 00:00:00 2001 From: Guilherme Blanco Date: Sun, 20 Apr 2014 14:40:51 +0000 Subject: [PATCH] DDC-3075 Added support for subqueries in NEW operator. --- lib/Doctrine/ORM/Query/Parser.php | 17 +++++++++++++---- lib/Doctrine/ORM/Query/SqlWalker.php | 16 +++++++++++----- .../Tests/ORM/Query/LanguageRecognitionTest.php | 8 ++++++++ .../Tests/ORM/Query/SelectSqlGenerationTest.php | 4 ++++ 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php index cd7909dd7..d010ad45d 100644 --- a/lib/Doctrine/ORM/Query/Parser.php +++ b/lib/Doctrine/ORM/Query/Parser.php @@ -1811,14 +1811,23 @@ class Parser } /** - * NewObjectArg ::= ScalarExpression + * NewObjectArg ::= ScalarExpression | "(" Subselect ")" * - * @TODO - Maybe you should support other expressions and nested "new" operator - * - * @return \Doctrine\ORM\Query\AST\SimpleSelectExpression + * @return mixed */ public function NewObjectArg() { + $token = $this->lexer->lookahead; + $peek = $this->lexer->glimpse(); + + if ($token['type'] === Lexer::T_OPEN_PARENTHESIS && $peek['type'] === Lexer::T_SELECT) { + $this->match(Lexer::T_OPEN_PARENTHESIS); + $expression = $this->Subselect(); + $this->match(Lexer::T_CLOSE_PARENTHESIS); + + return $expression; + } + return $this->ScalarExpression(); } diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index 5fd094915..8440bc176 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -1503,25 +1503,25 @@ class SqlWalker implements TreeWalker foreach ($newObjectExpression->args as $argIndex => $e) { $resultAlias = $this->scalarResultCounter++; $columnAlias = $this->getSQLColumnAlias('sclr'); + $fieldType = 'string'; switch (true) { case ($e instanceof AST\NewObjectExpression): $sqlSelectExpressions[] = $e->dispatch($this); break; - default: - $sqlSelectExpressions[] = trim($e->dispatch($this)) . ' AS ' . $columnAlias; + case ($e instanceof AST\Subselect): + $sqlSelectExpressions[] = '(' . $e->dispatch($this) . ') AS ' . $columnAlias; break; - } - $fieldType = 'string'; - switch (true) { case ($e instanceof AST\PathExpression): $fieldName = $e->field; $dqlAlias = $e->identificationVariable; $qComp = $this->queryComponents[$dqlAlias]; $class = $qComp['metadata']; $fieldType = $class->getTypeOfField($fieldName); + + $sqlSelectExpressions[] = trim($e->dispatch($this)) . ' AS ' . $columnAlias; break; case ($e instanceof AST\Literal): @@ -1534,6 +1534,12 @@ class SqlWalker implements TreeWalker $fieldType = is_float($e->value) ? 'float' : 'integer'; break; } + + $sqlSelectExpressions[] = trim($e->dispatch($this)) . ' AS ' . $columnAlias; + break; + + default: + $sqlSelectExpressions[] = trim($e->dispatch($this)) . ' AS ' . $columnAlias; break; } diff --git a/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php b/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php index d7fa0cbf8..096a1115d 100644 --- a/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php +++ b/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php @@ -612,6 +612,14 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase { $this->assertValidDQL("SELECT new " . __NAMESPACE__ . "\\DummyStruct(u.id, 'foo', 1, true) FROM Doctrine\Tests\Models\CMS\CmsUser u"); } + + /** + * @group DDC-3075 + */ + public function testNewLiteralWithSubselectExpression() + { + $this->assertValidDQL("SELECT new " . __NAMESPACE__ . "\\DummyStruct(u.id, 'foo', (SELECT 1 FROM Doctrine\Tests\Models\CMS\CmsUser su), true) FROM Doctrine\Tests\Models\CMS\CmsUser u"); + } } /** @Entity */ diff --git a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php index 339363191..918433ff1 100644 --- a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php +++ b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php @@ -1707,6 +1707,10 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase "SELECT c0_.id AS sclr_0, c0_.country AS sclr_1, c0_.city AS sclr_2, c1_.name AS sclr_3, c2_.email AS sclr_4 FROM cms_users c1_ INNER JOIN cms_emails c2_ ON c1_.email_id = c2_.id INNER JOIN cms_addresses c0_ ON c1_.id = c0_.user_id ORDER BY c1_.name ASC" ); + $this->assertSqlGeneration( + "SELECT new Doctrine\Tests\Models\CMS\CmsUserDTO(a.id, (SELECT 1 FROM Doctrine\Tests\Models\CMS\CmsUser su), a.country, a.city), new Doctrine\Tests\Models\CMS\CmsAddressDTO(u.name, e.email) FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.email e JOIN u.address a ORDER BY u.name", + "SELECT c0_.id AS sclr_0, (SELECT 1 AS sclr_2 FROM cms_users c1_) AS sclr_1, c0_.country AS sclr_3, c0_.city AS sclr_4, c2_.name AS sclr_5, c3_.email AS sclr_6 FROM cms_users c2_ INNER JOIN cms_emails c3_ ON c2_.email_id = c3_.id INNER JOIN cms_addresses c0_ ON c2_.id = c0_.user_id ORDER BY c2_.name ASC" + ); } /**