basic support refactory
This commit is contained in:
parent
b29d47a682
commit
2b403b7dad
@ -235,7 +235,7 @@ abstract class AbstractHydrator
|
|||||||
continue 2;
|
continue 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset ($this->_rsm->newObjectMappings[$key])) {
|
if (isset($this->_rsm->newObjectMappings[$key])) {
|
||||||
$cache[$key]['isNewObjectParameter'] = true;
|
$cache[$key]['isNewObjectParameter'] = true;
|
||||||
$cache[$key]['argIndex'] = $this->_rsm->newObjectMappings[$key]['argIndex'];
|
$cache[$key]['argIndex'] = $this->_rsm->newObjectMappings[$key]['argIndex'];
|
||||||
$cache[$key]['objIndex'] = $this->_rsm->newObjectMappings[$key]['objIndex'];
|
$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'];
|
$argIndex = $cache[$key]['argIndex'];
|
||||||
$objIndex = $cache[$key]['objIndex'];
|
$objIndex = $cache[$key]['objIndex'];
|
||||||
$rowData['newObjects'][$objIndex]['class'] = $cache[$key]['class'];
|
$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
|
* @return \Doctrine\ORM\Query\AST\NewObjectExpression
|
||||||
*/
|
*/
|
||||||
public function NewObjectExpression()
|
public function NewObjectExpression()
|
||||||
@ -1643,19 +1643,19 @@ class Parser
|
|||||||
if ( ! class_exists($className, true)) {
|
if ( ! class_exists($className, true)) {
|
||||||
$this->semanticalError("Class '$className' is not defined.", $this->_lexer->token);
|
$this->semanticalError("Class '$className' is not defined.", $this->_lexer->token);
|
||||||
}
|
}
|
||||||
|
|
||||||
$class = new \ReflectionClass($className);
|
$class = new \ReflectionClass($className);
|
||||||
if($class->getConstructor() === null) {
|
if($class->getConstructor() === null) {
|
||||||
$this->semanticalError("Class '$className' has not a valid contructor.", $this->_lexer->token);
|
$this->semanticalError("Class '$className' has not a valid contructor.", $this->_lexer->token);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->match(Lexer::T_OPEN_PARENTHESIS);
|
$this->match(Lexer::T_OPEN_PARENTHESIS);
|
||||||
|
|
||||||
$args[] = $this->SelectExpression();
|
$args[] = $this->NewObjectArg();
|
||||||
while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
|
while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
|
||||||
$this->match(Lexer::T_COMMA);
|
$this->match(Lexer::T_COMMA);
|
||||||
|
|
||||||
$args[] = $this->SelectExpression();
|
$args[] = $this->NewObjectArg();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->match(Lexer::T_CLOSE_PARENTHESIS);
|
$this->match(Lexer::T_CLOSE_PARENTHESIS);
|
||||||
@ -1664,10 +1664,41 @@ class Parser
|
|||||||
$this->semanticalError("Number of arguments does not match definition.", $this->_lexer->token);
|
$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;
|
break;
|
||||||
|
|
||||||
case ($expr instanceof AST\NewObjectExpression):
|
case ($expr instanceof AST\NewObjectExpression):
|
||||||
$sqlSelectExpressions = array();
|
|
||||||
$this->_rsm->newObjectMappings['className'] = $expr->className;
|
|
||||||
|
|
||||||
$sqlSelectExpressions = array();
|
$sqlSelectExpressions = array();
|
||||||
$objIndex = $this->newObjectCounter ++;
|
$objIndex = $this->newObjectCounter ++;
|
||||||
foreach ($expr->args as $key => $e) {
|
foreach ($expr->args as $argIndex => $e) {
|
||||||
|
|
||||||
|
$resultAlias = $this->scalarResultCounter++;
|
||||||
|
$columnAlias = $this->getSQLColumnAlias('sclr') . $resultAlias;
|
||||||
$resultAliasMap = $this->scalarResultAliasMap;
|
$resultAliasMap = $this->scalarResultAliasMap;
|
||||||
$sqlSelectExpressions[] = $this->walkSelectExpression($e);
|
$sqlSelectExpressions[] = $this->walkSimpleSelectExpression($e) . ' AS ' . $columnAlias;
|
||||||
$scalarResultAliasMap = array_diff($this->scalarResultAliasMap, $resultAliasMap);
|
|
||||||
foreach ($scalarResultAliasMap as $aliasMap) {
|
|
||||||
$this->_rsm->newObjectMappings[$aliasMap] = array(
|
$this->scalarResultAliasMap[$resultAlias] = $columnAlias;
|
||||||
'className' => $expr->className,
|
$this->rsm->addScalarResult($columnAlias, $resultAlias, 'string');
|
||||||
'objIndex' => $objIndex,
|
|
||||||
'argIndex' => $key
|
$this->rsm->newObjectMappings[$columnAlias] = array(
|
||||||
);
|
'className' => $expr->className,
|
||||||
}
|
'objIndex' => $objIndex,
|
||||||
|
'argIndex' => $argIndex
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql .= implode(', ', $sqlSelectExpressions);
|
$sql .= implode(',', $sqlSelectExpressions);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
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 $name;
|
||||||
public $email;
|
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->name = $name;
|
||||||
$this->email = $email;
|
$this->email = $email;
|
||||||
$this->city = $city;
|
$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->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $users[2]);
|
||||||
$this->assertNull($users[3]);
|
$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(
|
$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 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…
x
Reference in New Issue
Block a user