From f0403a539474ac7453bdac9cacb12814bad4be96 Mon Sep 17 00:00:00 2001 From: "Fabio B. Silva" Date: Sat, 11 Aug 2012 14:01:57 -0300 Subject: [PATCH] test literal values --- .../ORM/Query/AST/NewObjectExpression.php | 2 +- lib/Doctrine/ORM/Query/Parser.php | 32 +---- lib/Doctrine/ORM/Query/SqlWalker.php | 30 ++++- .../Tests/ORM/Functional/NewOperatorTest.php | 110 ++++++++++++++++++ .../ORM/Query/SelectSqlGenerationTest.php | 5 + 5 files changed, 149 insertions(+), 30 deletions(-) diff --git a/lib/Doctrine/ORM/Query/AST/NewObjectExpression.php b/lib/Doctrine/ORM/Query/AST/NewObjectExpression.php index c92481a62..5ddaf0a5e 100644 --- a/lib/Doctrine/ORM/Query/AST/NewObjectExpression.php +++ b/lib/Doctrine/ORM/Query/AST/NewObjectExpression.php @@ -20,7 +20,7 @@ namespace Doctrine\ORM\Query\AST; /** - * NewObjectExpression ::= "NEW" IdentificationVariable "(" SelectExpression {"," SelectExpression}* ")" + * NewObjectExpression ::= "NEW" IdentificationVariable "(" NewObjectArg {"," NewObjectArg}* ")" * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.org diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php index d8e982a75..a245afebb 100644 --- a/lib/Doctrine/ORM/Query/Parser.php +++ b/lib/Doctrine/ORM/Query/Parser.php @@ -1669,37 +1669,15 @@ class Parser } /** + * NewObjectArg ::= ScalarExpression + * + * @TODO - Maybe you should support other expressions and nested "new" operator + * * @return \Doctrine\ORM\Query\AST\SimpleSelectExpression */ public function NewObjectArg() { - $peek = $this->_lexer->glimpse(); - - switch (true) { - case ($peek['type'] === Lexer::T_DOT): - $expression = $this->StateFieldPathExpression(); - - return new AST\SimpleSelectExpression($expression); - - default: - if ( ! ($this->_isFunction() || $this->_isAggregateFunction($this->_lexer->lookahead))) { - $this->syntaxError(); - } - - // We may be in an ArithmeticExpression (find the matching ")" and inspect for Math operator) - $this->_lexer->peek(); // "(" - $peek = $this->_peekBeyondClosingParenthesis(); - - if ($this->_isMathOperator($peek)) { - return $this->SimpleArithmeticExpression(); - } - - if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) { - return $this->AggregateExpression(); - } - - return $this->FunctionDeclaration(); - } + return $this->ScalarExpression(); } /** diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index 71b88ec5d..a24b92836 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -1405,9 +1405,9 @@ class SqlWalker implements TreeWalker */ public function walkNewObject($newObjectExpression) { - $sqlSelectExpressions = array(); $objIndex = $this->newObjectCounter ++; + foreach ($newObjectExpression->args as $argIndex => $e) { $resultAlias = $this->scalarResultCounter++; @@ -1424,8 +1424,34 @@ class SqlWalker implements TreeWalker } + switch (true) { + case ($e instanceof AST\PathExpression): + $fieldName = $e->field; + $dqlAlias = $e->identificationVariable; + $qComp = $this->queryComponents[$dqlAlias]; + $class = $qComp['metadata']; + $fieldType = $class->getTypeOfField($fieldName); + break; + + case ($e instanceof AST\Literal): + switch ($e->type) { + case AST\Literal::BOOLEAN: + $fieldType = 'boolean'; + break; + + case AST\Literal::NUMERIC: + $fieldType = is_float($e->value) ? 'float' : 'integer'; + break; + } + break; + + default: + $fieldType = 'string'; + break; + } + $this->scalarResultAliasMap[$resultAlias] = $columnAlias; - $this->rsm->addScalarResult($columnAlias, $resultAlias); + $this->rsm->addScalarResult($columnAlias, $resultAlias, $fieldType); $this->rsm->newObjectMappings[$columnAlias] = array( 'className' => $newObjectExpression->className, diff --git a/tests/Doctrine/Tests/ORM/Functional/NewOperatorTest.php b/tests/Doctrine/Tests/ORM/Functional/NewOperatorTest.php index 7f56bc6c5..7797445b9 100644 --- a/tests/Doctrine/Tests/ORM/Functional/NewOperatorTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/NewOperatorTest.php @@ -129,6 +129,116 @@ class NewOperatorTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertEquals($this->fixtures[2]->address->city, $result[2]->address); } + public function testShouldSupportLiteral() + { + $dql = " + SELECT + new Doctrine\Tests\Models\CMS\CmsUserDTO( + u.name, + 'fabio.bat.silva@gmail.com', + FALSE, + 123 + ) + FROM + Doctrine\Tests\Models\CMS\CmsUser u + JOIN + u.email e + JOIN + u.address a + JOIN + u.phonenumbers p + GROUP BY + u, e, a + ORDER BY + u.name"; + + $query = $this->_em->createQuery($dql); + $result = $query->getResult(); + + $this->assertCount(3, $result); + + $this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUserDTO', $result[0]); + $this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUserDTO', $result[1]); + $this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUserDTO', $result[2]); + + + $this->assertEquals($this->fixtures[0]->name, $result[0]->name); + $this->assertEquals($this->fixtures[1]->name, $result[1]->name); + $this->assertEquals($this->fixtures[2]->name, $result[2]->name); + + $this->assertEquals('fabio.bat.silva@gmail.com', $result[0]->email); + $this->assertEquals('fabio.bat.silva@gmail.com', $result[1]->email); + $this->assertEquals('fabio.bat.silva@gmail.com', $result[2]->email); + + $this->assertEquals(false, $result[0]->address); + $this->assertEquals(false, $result[1]->address); + $this->assertEquals(false, $result[2]->address); + + $this->assertEquals(123, $result[0]->phonenumbers); + $this->assertEquals(123, $result[1]->phonenumbers); + $this->assertEquals(123, $result[2]->phonenumbers); + } + + public function testShouldSupportSimpleArithmeticExpression() + { + $dql = " + SELECT + new Doctrine\Tests\Models\CMS\CmsUserDTO( + u.name, + e.email, + a.city, + a.id + u.id + ) + FROM + Doctrine\Tests\Models\CMS\CmsUser u + JOIN + u.email e + JOIN + u.address a + JOIN + u.phonenumbers p + GROUP BY + u, e, a + ORDER BY + u.name"; + + $query = $this->_em->createQuery($dql); + $result = $query->getResult(); + + $this->assertCount(3, $result); + + $this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUserDTO', $result[0]); + $this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUserDTO', $result[1]); + $this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUserDTO', $result[2]); + + $this->assertEquals($this->fixtures[0]->name, $result[0]->name); + $this->assertEquals($this->fixtures[1]->name, $result[1]->name); + $this->assertEquals($this->fixtures[2]->name, $result[2]->name); + + $this->assertEquals($this->fixtures[0]->email->email, $result[0]->email); + $this->assertEquals($this->fixtures[1]->email->email, $result[1]->email); + $this->assertEquals($this->fixtures[2]->email->email, $result[2]->email); + + $this->assertEquals($this->fixtures[0]->address->city, $result[0]->address); + $this->assertEquals($this->fixtures[1]->address->city, $result[1]->address); + $this->assertEquals($this->fixtures[2]->address->city, $result[2]->address); + + $this->assertEquals( + ($this->fixtures[0]->address->id + $this->fixtures[0]->id), + $result[0]->phonenumbers + ); + + $this->assertEquals( + ($this->fixtures[1]->address->id + $this->fixtures[1]->id), + $result[1]->phonenumbers + ); + + $this->assertEquals( + ($this->fixtures[2]->address->id + $this->fixtures[2]->id), + $result[2]->phonenumbers + ); + } + public function testShouldSupportAggregateFunctions() { $dql = " diff --git a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php index fdedb921a..573621d25 100644 --- a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php +++ b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php @@ -1565,6 +1565,11 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase 'SELECT c0_.name AS sclr0, c1_.email AS sclr1, c2_.city AS sclr2 FROM cms_users c0_ INNER JOIN cms_emails c1_ ON c0_.email_id = c1_.id INNER JOIN cms_addresses c2_ ON c0_.id = c2_.user_id' ); + $this->assertSqlGeneration( + 'SELECT new Doctrine\Tests\Models\CMS\CmsUserDTO(u.name, e.email, a.id + u.id) FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.email e JOIN u.address a', + "SELECT c0_.name AS sclr0, c1_.email AS sclr1, c2_.id + c0_.id AS sclr2 FROM cms_users c0_ INNER JOIN cms_emails c1_ ON c0_.email_id = c1_.id INNER JOIN cms_addresses c2_ ON c0_.id = c2_.user_id" + ); + $this->assertSqlGeneration( 'SELECT new Doctrine\Tests\Models\CMS\CmsUserDTO(u.name, e.email, a.city, COUNT(p)) FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.email e JOIN u.address a JOIN u.phonenumbers p', 'SELECT c0_.name AS sclr0, c1_.email AS sclr1, c2_.city AS sclr2, COUNT(c3_.phonenumber) AS sclr3 FROM cms_users c0_ INNER JOIN cms_emails c1_ ON c0_.email_id = c1_.id INNER JOIN cms_addresses c2_ ON c0_.id = c2_.user_id INNER JOIN cms_phonenumbers c3_ ON c0_.id = c3_.user_id'