Commit 3928ba9d authored by guilhermeblanco's avatar guilhermeblanco

[2.0] Added support to complex PathExpression in DQL queries

parent 20c84166
This diff is collapsed.
...@@ -414,9 +414,8 @@ class SqlWalker implements TreeWalker ...@@ -414,9 +414,8 @@ class SqlWalker implements TreeWalker
switch ($pathExpr->type) { switch ($pathExpr->type) {
case AST\PathExpression::TYPE_STATE_FIELD: case AST\PathExpression::TYPE_STATE_FIELD:
$parts = $pathExpr->parts; $parts = $pathExpr->parts;
$numParts = count($parts); $fieldName = array_pop($parts);
$dqlAlias = $pathExpr->identificationVariable; $dqlAlias = $pathExpr->identificationVariable . (( ! empty($parts)) ? '.' . implode('.', $parts) : '');
$fieldName = $parts[$numParts - 1];
$qComp = $this->_queryComponents[$dqlAlias]; $qComp = $this->_queryComponents[$dqlAlias];
$class = $qComp['metadata']; $class = $qComp['metadata'];
...@@ -609,20 +608,18 @@ class SqlWalker implements TreeWalker ...@@ -609,20 +608,18 @@ class SqlWalker implements TreeWalker
*/ */
public function walkOrderByItem($orderByItem) public function walkOrderByItem($orderByItem)
{ {
$sql = '';
$expr = $orderByItem->expression; $expr = $orderByItem->expression;
if ($expr instanceof AST\PathExpression) { if ($expr instanceof AST\PathExpression) {
$parts = $expr->parts; $sql = $this->walkPathExpression($expr);
$dqlAlias = $expr->identificationVariable;
$class = $this->_queryComponents[$dqlAlias]['metadata'];
$columnName = $class->getQuotedColumnName($parts[0], $this->_platform);
return $this->getSqlTableAlias($class->getTableName(), $dqlAlias) . '.'
. $columnName . ' ' . strtoupper($orderByItem->type);
} else { } else {
$columnName = $this->_queryComponents[$expr]['token']['value']; $columnName = $this->_queryComponents[$expr]['token']['value'];
return $this->_scalarResultAliasMap[$columnName] . ' ' . strtoupper($orderByItem->type); $sql = $this->_scalarResultAliasMap[$columnName];
} }
return $sql . ' ' . strtoupper($orderByItem->type);;
} }
/** /**
...@@ -771,16 +768,15 @@ class SqlWalker implements TreeWalker ...@@ -771,16 +768,15 @@ class SqlWalker implements TreeWalker
if ($expr instanceof AST\PathExpression) { if ($expr instanceof AST\PathExpression) {
if ($expr->type == AST\PathExpression::TYPE_STATE_FIELD) { if ($expr->type == AST\PathExpression::TYPE_STATE_FIELD) {
$parts = $expr->parts; $parts = $expr->parts;
$numParts = count($parts); $fieldName = array_pop($parts);
$dqlAlias = $expr->identificationVariable; $dqlAlias = $expr->identificationVariable . (( ! empty($parts)) ? '.' . implode('.', $parts) : '');
$fieldName = $parts[$numParts - 1];
$qComp = $this->_queryComponents[$dqlAlias]; $qComp = $this->_queryComponents[$dqlAlias];
$class = $qComp['metadata']; $class = $qComp['metadata'];
if ( ! isset($this->_selectedClasses[$dqlAlias])) { if ( ! isset($this->_selectedClasses[$dqlAlias])) {
$this->_selectedClasses[$dqlAlias] = $class; $this->_selectedClasses[$dqlAlias] = $class;
} }
$sqlTableAlias = $this->getSqlTableAlias($class->getTableName(), $dqlAlias); $sqlTableAlias = $this->getSqlTableAlias($class->getTableName(), $dqlAlias);
$columnName = $class->getQuotedColumnName($fieldName, $this->_platform); $columnName = $class->getQuotedColumnName($fieldName, $this->_platform);
$columnAlias = $this->getSqlColumnAlias($class->columnNames[$fieldName]); $columnAlias = $this->getSqlColumnAlias($class->columnNames[$fieldName]);
...@@ -1004,17 +1000,8 @@ class SqlWalker implements TreeWalker ...@@ -1004,17 +1000,8 @@ class SqlWalker implements TreeWalker
*/ */
public function walkAggregateExpression($aggExpression) public function walkAggregateExpression($aggExpression)
{ {
$sql = '';
$parts = $aggExpression->pathExpression->parts;
$dqlAlias = $aggExpression->pathExpression->identificationVariable;
$fieldName = $parts[0];
$qComp = $this->_queryComponents[$dqlAlias];
$columnName = $qComp['metadata']->getQuotedColumnName($fieldName, $this->_platform);
return $aggExpression->functionName . '(' . ($aggExpression->isDistinct ? 'DISTINCT ' : '') return $aggExpression->functionName . '(' . ($aggExpression->isDistinct ? 'DISTINCT ' : '')
. $this->getSqlTableAlias($qComp['metadata']->getTableName(), $dqlAlias) . '.' . $this->walkPathExpression($aggExpression->pathExpression) . ')';
. $columnName . ')';
} }
/** /**
...@@ -1038,12 +1025,7 @@ class SqlWalker implements TreeWalker ...@@ -1038,12 +1025,7 @@ class SqlWalker implements TreeWalker
*/ */
public function walkGroupByItem(AST\PathExpression $pathExpr) public function walkGroupByItem(AST\PathExpression $pathExpr)
{ {
$parts = $pathExpr->parts; return $this->walkPathExpression($pathExpr);
$dqlAlias = $pathExpr->identificationVariable;
$qComp = $this->_queryComponents[$dqlAlias];
$columnName = $qComp['metadata']->getQuotedColumnName($parts[0], $this->_platform);
return $this->getSqlTableAlias($qComp['metadata']->getTableName(), $dqlAlias) . '.' . $columnName;
} }
/** /**
...@@ -1219,8 +1201,10 @@ class SqlWalker implements TreeWalker ...@@ -1219,8 +1201,10 @@ class SqlWalker implements TreeWalker
$sql .= 'EXISTS (SELECT 1 FROM '; $sql .= 'EXISTS (SELECT 1 FROM ';
$entityExpr = $collMemberExpr->entityExpression; $entityExpr = $collMemberExpr->entityExpression;
$collPathExpr = $collMemberExpr->collectionValuedPathExpression; $collPathExpr = $collMemberExpr->collectionValuedPathExpression;
$parts = $collPathExpr->parts; $parts = $collPathExpr->parts;
$dqlAlias = $collPathExpr->identificationVariable; $fieldName = array_pop($parts);
$dqlAlias = $collPathExpr->identificationVariable . (( ! empty($parts)) ? '.' . implode('.', $parts) : '');
$class = $this->_queryComponents[$dqlAlias]['metadata']; $class = $this->_queryComponents[$dqlAlias]['metadata'];
...@@ -1232,7 +1216,7 @@ class SqlWalker implements TreeWalker ...@@ -1232,7 +1216,7 @@ class SqlWalker implements TreeWalker
throw DoctrineException::notImplemented(); throw DoctrineException::notImplemented();
} }
$assoc = $class->associationMappings[$parts[0]]; $assoc = $class->associationMappings[$fieldName];
if ($assoc->isOneToMany()) { if ($assoc->isOneToMany()) {
$targetClass = $this->_em->getClassMetadata($assoc->targetEntityName); $targetClass = $this->_em->getClassMetadata($assoc->targetEntityName);
......
...@@ -58,6 +58,25 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase ...@@ -58,6 +58,25 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
return $parser->parse(); return $parser->parse();
} }
public function parseDqlForAST($dql, $hints = array())
{
$query = $this->_em->createQuery($dql);
$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
$query->setDql($dql);
foreach ($hints as $key => $value) {
$query->setHint($key, $value);
}
$parser = new \Doctrine\ORM\Query\Parser($query);
// We do NOT test SQL output here. That only unnecessarily slows down the tests!
$parser->setCustomOutputTreeWalker('Doctrine\Tests\Mocks\MockTreeWalker');
$parser->parse();
return $parser->getAST();
}
public function testEmptyQueryString() public function testEmptyQueryString()
{ {
...@@ -84,6 +103,11 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase ...@@ -84,6 +103,11 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
$this->assertValidDql('SELECT u, p FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.phonenumbers p'); $this->assertValidDql('SELECT u, p FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.phonenumbers p');
} }
public function testSelectMultipleComponentsWithAsterisk2()
{
$this->assertValidDql('SELECT a.user.name FROM Doctrine\Tests\Models\CMS\CmsArticle a');
}
public function testSelectDistinctIsSupported() public function testSelectDistinctIsSupported()
{ {
$this->assertValidDql('SELECT DISTINCT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u'); $this->assertValidDql('SELECT DISTINCT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u');
...@@ -93,6 +117,11 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase ...@@ -93,6 +117,11 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
{ {
$this->assertValidDql('SELECT COUNT(u.id) FROM Doctrine\Tests\Models\CMS\CmsUser u'); $this->assertValidDql('SELECT COUNT(u.id) FROM Doctrine\Tests\Models\CMS\CmsUser u');
} }
public function testDuplicatedAliasInAggregateFunction()
{
$this->assertInvalidDql('SELECT COUNT(u.id) AS num, SUM(u.id) AS num FROM Doctrine\Tests\Models\CMS\CmsUser u');
}
public function testAggregateFunctionWithDistinctInSelect() public function testAggregateFunctionWithDistinctInSelect()
{ {
......
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
namespace Doctrine\Tests\ORM\Query; namespace Doctrine\Tests\ORM\Query;
use Doctrine\ORM\Query; use Doctrine\ORM\Query,
Doctrine\Common\DoctrineException;
require_once __DIR__ . '/../../TestInit.php'; require_once __DIR__ . '/../../TestInit.php';
...@@ -22,7 +23,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase ...@@ -22,7 +23,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true); $query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
parent::assertEquals($sqlToBeConfirmed, $query->getSql()); parent::assertEquals($sqlToBeConfirmed, $query->getSql());
$query->free(); $query->free();
} catch (Doctrine_Exception $e) { } catch (DoctrineException $e) {
$this->fail($e->getMessage()); $this->fail($e->getMessage());
} }
} }
...@@ -42,6 +43,22 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase ...@@ -42,6 +43,22 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
'SELECT c0_.id AS id0 FROM cms_users c0_' 'SELECT c0_.id AS id0 FROM cms_users c0_'
); );
} }
public function testSupportsSelectForOneNestedField()
{
$this->assertSqlGeneration(
'SELECT a.user.id FROM Doctrine\Tests\Models\CMS\CmsArticle a',
'SELECT c0_.id AS id0 FROM cms_articles c1_ INNER JOIN cms_users c0_ ON c1_.user_id = c0_.id'
);
}
public function testSupportsSelectForAllNestedField()
{
$this->assertSqlGeneration(
'SELECT a FROM Doctrine\Tests\Models\CMS\CmsArticle a ORDER BY a.user.name ASC',
'SELECT c0_.id AS id0, c0_.topic AS topic1, c0_.text AS text2 FROM cms_articles c0_ INNER JOIN cms_users c1_ ON c0_.user_id = c1_.id ORDER BY c1_.name ASC'
);
}
public function testSupportsSelectForMultipleColumnsOfASingleComponent() public function testSupportsSelectForMultipleColumnsOfASingleComponent()
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment