1
0
mirror of synced 2024-12-13 14:56:01 +03:00

basic support refactory

This commit is contained in:
Fabio B. Silva 2012-06-30 18:15:09 -03:00
parent b29d47a682
commit 2b403b7dad
8 changed files with 241 additions and 93 deletions

View File

@ -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'];

View File

@ -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");
}
/**

View File

@ -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:

View 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;
}
}

View File

@ -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;
}
}

View 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();
}
}

View File

@ -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);
}
}
}

View File

@ -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'
);
}