basic support refactory
This commit is contained in:
parent
b29d47a682
commit
2b403b7dad
@ -235,7 +235,7 @@ abstract class AbstractHydrator
|
||||
continue 2;
|
||||
}
|
||||
|
||||
if (isset ($this->_rsm->newObjectMappings[$key])) {
|
||||
if (isset($this->_rsm->newObjectMappings[$key])) {
|
||||
$cache[$key]['isNewObjectParameter'] = true;
|
||||
$cache[$key]['argIndex'] = $this->_rsm->newObjectMappings[$key]['argIndex'];
|
||||
$cache[$key]['objIndex'] = $this->_rsm->newObjectMappings[$key]['objIndex'];
|
||||
@ -243,7 +243,7 @@ abstract class AbstractHydrator
|
||||
}
|
||||
}
|
||||
|
||||
if (isset ($cache[$key]['isNewObjectParameter'])) {
|
||||
if (isset($cache[$key]['isNewObjectParameter'])) {
|
||||
$argIndex = $cache[$key]['argIndex'];
|
||||
$objIndex = $cache[$key]['objIndex'];
|
||||
$rowData['newObjects'][$objIndex]['class'] = $cache[$key]['class'];
|
||||
|
@ -1630,7 +1630,7 @@ class Parser
|
||||
}
|
||||
|
||||
/**
|
||||
* NewObjectExpression ::= "NEW" IdentificationVariable "(" SelectExpression {"," SelectExpression}* ")"
|
||||
* NewObjectExpression ::= "NEW" IdentificationVariable "(" NewObjectArg {"," NewObjectArg}* ")"
|
||||
* @return \Doctrine\ORM\Query\AST\NewObjectExpression
|
||||
*/
|
||||
public function NewObjectExpression()
|
||||
@ -1643,19 +1643,19 @@ class Parser
|
||||
if ( ! class_exists($className, true)) {
|
||||
$this->semanticalError("Class '$className' is not defined.", $this->_lexer->token);
|
||||
}
|
||||
|
||||
|
||||
$class = new \ReflectionClass($className);
|
||||
if($class->getConstructor() === null) {
|
||||
$this->semanticalError("Class '$className' has not a valid contructor.", $this->_lexer->token);
|
||||
}
|
||||
|
||||
$this->match(Lexer::T_OPEN_PARENTHESIS);
|
||||
|
||||
$args[] = $this->SelectExpression();
|
||||
|
||||
$args[] = $this->NewObjectArg();
|
||||
while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
|
||||
$this->match(Lexer::T_COMMA);
|
||||
|
||||
$args[] = $this->SelectExpression();
|
||||
$args[] = $this->NewObjectArg();
|
||||
}
|
||||
|
||||
$this->match(Lexer::T_CLOSE_PARENTHESIS);
|
||||
@ -1664,10 +1664,41 @@ class Parser
|
||||
$this->semanticalError("Number of arguments does not match definition.", $this->_lexer->token);
|
||||
}
|
||||
|
||||
$expression = new AST\NewObjectExpression($className, $args);
|
||||
return new AST\NewObjectExpression($className, $args);;
|
||||
}
|
||||
|
||||
// @TODO : Defer NewObjectExpression validation ?
|
||||
return $expression;
|
||||
/**
|
||||
* @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);
|
||||
|
||||
case ($peek['type'] !== Lexer::T_OPEN_PARENTHESIS):
|
||||
$expression = $this->IdentificationVariable();
|
||||
|
||||
return new AST\SimpleSelectExpression($expression);
|
||||
|
||||
case ($this->_isFunction()):
|
||||
// SUM(u.id) + COUNT(u.id)
|
||||
if ($this->_isMathOperator($this->_peekBeyondClosingParenthesis())) {
|
||||
return new AST\SimpleSelectExpression($this->ScalarExpression());
|
||||
}
|
||||
// COUNT(u.id)
|
||||
if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
|
||||
return new AST\SimpleSelectExpression($this->AggregateExpression());
|
||||
}
|
||||
// IDENTITY(u)
|
||||
return new AST\SimpleSelectExpression($this->FunctionDeclaration());
|
||||
}
|
||||
|
||||
$this->semanticalError("Unsupported expression");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1229,25 +1229,28 @@ class SqlWalker implements TreeWalker
|
||||
break;
|
||||
|
||||
case ($expr instanceof AST\NewObjectExpression):
|
||||
$sqlSelectExpressions = array();
|
||||
$this->_rsm->newObjectMappings['className'] = $expr->className;
|
||||
|
||||
$sqlSelectExpressions = array();
|
||||
$objIndex = $this->newObjectCounter ++;
|
||||
foreach ($expr->args as $key => $e) {
|
||||
$sqlSelectExpressions = array();
|
||||
$objIndex = $this->newObjectCounter ++;
|
||||
foreach ($expr->args as $argIndex => $e) {
|
||||
|
||||
$resultAlias = $this->scalarResultCounter++;
|
||||
$columnAlias = $this->getSQLColumnAlias('sclr') . $resultAlias;
|
||||
$resultAliasMap = $this->scalarResultAliasMap;
|
||||
$sqlSelectExpressions[] = $this->walkSelectExpression($e);
|
||||
$scalarResultAliasMap = array_diff($this->scalarResultAliasMap, $resultAliasMap);
|
||||
foreach ($scalarResultAliasMap as $aliasMap) {
|
||||
$this->_rsm->newObjectMappings[$aliasMap] = array(
|
||||
'className' => $expr->className,
|
||||
'objIndex' => $objIndex,
|
||||
'argIndex' => $key
|
||||
);
|
||||
}
|
||||
$sqlSelectExpressions[] = $this->walkSimpleSelectExpression($e) . ' AS ' . $columnAlias;
|
||||
|
||||
|
||||
$this->scalarResultAliasMap[$resultAlias] = $columnAlias;
|
||||
$this->rsm->addScalarResult($columnAlias, $resultAlias, 'string');
|
||||
|
||||
$this->rsm->newObjectMappings[$columnAlias] = array(
|
||||
'className' => $expr->className,
|
||||
'objIndex' => $objIndex,
|
||||
'argIndex' => $argIndex
|
||||
);
|
||||
}
|
||||
|
||||
$sql .= implode(', ', $sqlSelectExpressions);
|
||||
$sql .= implode(',', $sqlSelectExpressions);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
17
tests/Doctrine/Tests/Models/CMS/CmsAddressDTO.php
Normal file
17
tests/Doctrine/Tests/Models/CMS/CmsAddressDTO.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\Models\CMS;
|
||||
|
||||
class CmsAddressDTO
|
||||
{
|
||||
public $country;
|
||||
public $city;
|
||||
public $zip;
|
||||
|
||||
public function __construct($country = null, $city = null, $zip = null)
|
||||
{
|
||||
$this->country = $country;
|
||||
$this->city = $city;
|
||||
$this->zip = $zip;
|
||||
}
|
||||
}
|
@ -6,12 +6,12 @@ class CmsUserDTO
|
||||
{
|
||||
public $name;
|
||||
public $email;
|
||||
public $city;
|
||||
public $address;
|
||||
|
||||
public function __construct($name = null, $email = null, $city = null)
|
||||
public function __construct($name = null, $email = null, $address = null)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->email = $email;
|
||||
$this->city = $city;
|
||||
$this->name = $name;
|
||||
$this->email = $email;
|
||||
$this->address = $address;
|
||||
}
|
||||
}
|
158
tests/Doctrine/Tests/ORM/Functional/NewOperatorTest.php
Normal file
158
tests/Doctrine/Tests/ORM/Functional/NewOperatorTest.php
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\Tests\Models\CMS\CmsUser;
|
||||
use Doctrine\Tests\Models\CMS\CmsEmail;
|
||||
use Doctrine\Tests\Models\CMS\CmsArticle;
|
||||
use Doctrine\Tests\Models\CMS\CmsAddress;
|
||||
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
|
||||
|
||||
require_once __DIR__ . '/../../TestInit.php';
|
||||
|
||||
/**
|
||||
* @group DDC-1574
|
||||
*/
|
||||
class NewOperatorTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $fixtures;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->useModelSet('cms');
|
||||
parent::setUp();
|
||||
|
||||
$this->loadFixtures();
|
||||
}
|
||||
|
||||
private function loadFixtures()
|
||||
{
|
||||
$u1 = new CmsUser;
|
||||
$u2 = new CmsUser;
|
||||
$u3 = new CmsUser;
|
||||
|
||||
$u1->setEmail(new CmsEmail());
|
||||
$u1->setAddress(new CmsAddress());
|
||||
|
||||
$u2->setEmail(new CmsEmail());
|
||||
$u2->setAddress(new CmsAddress());
|
||||
|
||||
$u3->setEmail(new CmsEmail());
|
||||
$u3->setAddress(new CmsAddress());
|
||||
|
||||
$u1->name = 'Test 1';
|
||||
$u1->username = '1test';
|
||||
$u1->status = 'developer';
|
||||
$u1->email->email = 'email@test1.com';
|
||||
$u1->address->zip = '111111111';
|
||||
$u1->address->city = 'Some City 1';
|
||||
$u1->address->country = 'Some Country 2';
|
||||
|
||||
$u2->name = 'Test 2';
|
||||
$u2->username = '2test';
|
||||
$u2->status = 'developer';
|
||||
$u2->email->email = 'email@test2.com';
|
||||
$u2->address->zip = '222222222';
|
||||
$u2->address->city = 'Some City 2';
|
||||
$u2->address->country = 'Some Country 2';
|
||||
|
||||
$u3->name = 'Test 3';
|
||||
$u3->username = '3test';
|
||||
$u3->status = 'developer';
|
||||
$u3->email->email = 'email@test3.com';
|
||||
$u3->address->zip = '33333333';
|
||||
$u3->address->city = 'Some City 3';
|
||||
$u3->address->country = 'Some Country 3';
|
||||
|
||||
$this->_em->persist($u1);
|
||||
$this->_em->persist($u2);
|
||||
$this->_em->persist($u3);
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$this->fixtures = array($u1, $u2, $u3);
|
||||
}
|
||||
|
||||
public function testShouldSupportsBasicUsage()
|
||||
{
|
||||
$dql = "
|
||||
SELECT
|
||||
new Doctrine\Tests\Models\CMS\CmsUserDTO(
|
||||
u.name,
|
||||
e.email,
|
||||
a.city
|
||||
)
|
||||
FROM
|
||||
Doctrine\Tests\Models\CMS\CmsUser u
|
||||
JOIN
|
||||
u.email e
|
||||
JOIN
|
||||
u.address 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);
|
||||
}
|
||||
|
||||
public function testShouldSupportNestedOperators()
|
||||
{
|
||||
$this->markTestIncomplete();
|
||||
$dql = "
|
||||
SELECT
|
||||
new Doctrine\Tests\Models\CMS\CmsUserDTO(
|
||||
u.name,
|
||||
e.email,
|
||||
new Doctrine\Tests\Models\CMS\CmsUserDTO(a.country, a.city, a.zip)
|
||||
)
|
||||
FROM
|
||||
Doctrine\Tests\Models\CMS\CmsUser u
|
||||
JOIN
|
||||
u.email e
|
||||
JOIN
|
||||
u.address 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]);
|
||||
|
||||
}
|
||||
|
||||
public function testShouldSupportAggregateFunctions()
|
||||
{
|
||||
$this->markTestIncomplete();
|
||||
}
|
||||
}
|
@ -780,65 +780,4 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $users[2]);
|
||||
$this->assertNull($users[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1574
|
||||
*/
|
||||
public function testSupportsNewOperator()
|
||||
{
|
||||
$u1 = new CmsUser;
|
||||
$u2 = new CmsUser;
|
||||
$u3 = new CmsUser;
|
||||
|
||||
$u1->setEmail(new \Doctrine\Tests\Models\CMS\CmsEmail());
|
||||
$u1->setAddress(new \Doctrine\Tests\Models\CMS\CmsAddress());
|
||||
|
||||
$u2->setEmail(new \Doctrine\Tests\Models\CMS\CmsEmail());
|
||||
$u2->setAddress(new \Doctrine\Tests\Models\CMS\CmsAddress());
|
||||
|
||||
$u3->setEmail(new \Doctrine\Tests\Models\CMS\CmsEmail());
|
||||
$u3->setAddress(new \Doctrine\Tests\Models\CMS\CmsAddress());
|
||||
|
||||
$u1->name = 'Test 1';
|
||||
$u1->username = '1test';
|
||||
$u1->status = 'developer';
|
||||
$u1->email->email = 'email@test1.com';
|
||||
$u1->address->zip = '111111111';
|
||||
$u1->address->city = 'Some City 1';
|
||||
$u1->address->country = 'Some Country 2';
|
||||
|
||||
$u2->name = 'Test 2';
|
||||
$u2->username = '2test';
|
||||
$u2->status = 'developer';
|
||||
$u2->email->email = 'email@test2.com';
|
||||
$u2->address->zip = '111111111';
|
||||
$u2->address->city = 'Some City 2';
|
||||
$u2->address->country = 'Some Country 2';
|
||||
|
||||
$u3->name = 'Fabio Silva';
|
||||
$u3->username = 'FabioBatSilva';
|
||||
$u3->status = 'developer';
|
||||
$u3->email->email = 'fabio.bat.silva@gmail.com';
|
||||
$u3->address->zip = '33333333';
|
||||
$u3->address->city = 'Some City 3';
|
||||
$u3->address->country = 'Some Country 3';
|
||||
|
||||
$this->_em->persist($u1);
|
||||
$this->_em->persist($u2);
|
||||
$this->_em->persist($u3);
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$query = $this->_em->createQuery("SELECT new Doctrine\Tests\Models\CMS\CmsUserDTO(u.name, e.email, a.city) FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.email e JOIN u.address a ORDER BY u.name");
|
||||
$result = $query->getResult();
|
||||
|
||||
$this->assertCount(3, $result);
|
||||
|
||||
$this->markTestIncomplete();
|
||||
|
||||
$this->assertTrue($result[0] instanceof \Doctrine\Tests\Models\CMS\CmsUserDTO);
|
||||
$this->assertTrue($result[1] instanceof \Doctrine\Tests\Models\CMS\CmsUserDTO);
|
||||
$this->assertTrue($result[2] instanceof \Doctrine\Tests\Models\CMS\CmsUserDTO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1562,7 +1562,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT new Doctrine\Tests\Models\CMS\CmsUserDTO(u.name, e.email, a.city) FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.email e JOIN u.address a',
|
||||
'SELECT c0_.name AS name0, c1_.email AS email1, c2_.city AS city2 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'
|
||||
'SELECT c0_.name AS sclr01, c1_.email AS sclr12, c2_.city AS sclr23 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'
|
||||
);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user