Skip to content

Commit

Permalink
Merge pull request #686 from FabioBatSilva/DDC-2475
Browse files Browse the repository at this point in the history
[DDC-2475] Replace OrderBy mapping when OrderByClause is given
  • Loading branch information
guilhermeblanco committed Jun 5, 2013
2 parents 3d6436c + 2751137 commit 753d63c
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 38 deletions.
106 changes: 68 additions & 38 deletions lib/Doctrine/ORM/Query/SqlWalker.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query;
use Doctrine\ORM\Query\QueryException;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\Mapping\ClassMetadataInfo;

/**
Expand Down Expand Up @@ -117,6 +118,13 @@ class SqlWalker implements TreeWalker
*/
private $scalarResultAliasMap = array();

/**
* Map from Table-Alias + Column-Name to OrderBy-Direction.
*
* @var array
*/
private $orderedColumnsMap = array();

/**
* Map from DQL-Alias + Field-Name to SQL Column Alias.
*
Expand Down Expand Up @@ -388,25 +396,36 @@ private function _generateClassTableInheritanceJoins($class, $dqlAlias)
*/
private function _generateOrderedCollectionOrderByItems()
{
$sqlParts = array();
$orderedColumns = array();

foreach ($this->selectedClasses as $selectedClass) {
$dqlAlias = $selectedClass['dqlAlias'];
$qComp = $this->queryComponents[$dqlAlias];
$dqlAlias = $selectedClass['dqlAlias'];
$qComp = $this->queryComponents[$dqlAlias];
$persister = $this->em->getUnitOfWork()->getEntityPersister($qComp['metadata']->name);

if ( ! isset($qComp['relation']['orderBy'])) continue;
if ( ! isset($qComp['relation']['orderBy'])) {
continue;
}

foreach ($qComp['relation']['orderBy'] as $fieldName => $orientation) {
$columnName = $this->quoteStrategy->getColumnName($fieldName, $qComp['metadata'], $this->platform);
$tableName = ($qComp['metadata']->isInheritanceTypeJoined())
? $this->em->getUnitOfWork()->getEntityPersister($qComp['metadata']->name)->getOwningTable($fieldName)
? $persister->getOwningTable($fieldName)
: $qComp['metadata']->getTableName();

$sqlParts[] = $this->getSQLTableAlias($tableName, $dqlAlias) . '.' . $columnName . ' ' . $orientation;
$orderedColumn = $this->getSQLTableAlias($tableName, $dqlAlias) . '.' . $columnName;

// OrderByClause should replace an ordered relation. see - DDC-2475
if (isset($this->orderedColumnsMap[$orderedColumn])) {
continue;
}

$this->orderedColumnsMap[$orderedColumn] = $orientation;
$orderedColumns[] = $orderedColumn . ' ' . $orientation;
}
}

return implode(', ', $sqlParts);
return implode(', ', $orderedColumns);
}

/**
Expand Down Expand Up @@ -495,44 +514,52 @@ private function generateFilterConditionSQL(ClassMetadata $targetEntity, $target
*/
public function walkSelectStatement(AST\SelectStatement $AST)
{
$sql = $this->walkSelectClause($AST->selectClause);
$sql .= $this->walkFromClause($AST->fromClause);
$sql .= $this->walkWhereClause($AST->whereClause);
$sql .= $AST->groupByClause ? $this->walkGroupByClause($AST->groupByClause) : '';
$sql .= $AST->havingClause ? $this->walkHavingClause($AST->havingClause) : '';
$limit = $this->query->getMaxResults();
$offset = $this->query->getFirstResult();
$lockMode = $this->query->getHint(Query::HINT_LOCK_MODE);
$sql = $this->walkSelectClause($AST->selectClause)
. $this->walkFromClause($AST->fromClause)
. $this->walkWhereClause($AST->whereClause);

if (($orderByClause = $AST->orderByClause) !== null) {
$sql .= $AST->orderByClause ? $this->walkOrderByClause($AST->orderByClause) : '';
} else if (($orderBySql = $this->_generateOrderedCollectionOrderByItems()) !== '') {
if ($AST->groupByClause) {
$sql .= $this->walkGroupByClause($AST->groupByClause);
}

if ($AST->havingClause) {
$sql .= $this->walkHavingClause($AST->havingClause);
}

if ($AST->orderByClause) {
$sql .= $this->walkOrderByClause($AST->orderByClause);
}

if ( ! $AST->orderByClause && ($orderBySql = $this->_generateOrderedCollectionOrderByItems())) {
$sql .= ' ORDER BY ' . $orderBySql;
}

$sql = $this->platform->modifyLimitQuery(
$sql, $this->query->getMaxResults(), $this->query->getFirstResult()
);
if ($limit !== null || $offset !== null) {
$sql = $this->platform->modifyLimitQuery($sql, $limit, $offset);
}

if (($lockMode = $this->query->getHint(Query::HINT_LOCK_MODE)) !== false) {
switch ($lockMode) {
case LockMode::PESSIMISTIC_READ:
$sql .= ' ' . $this->platform->getReadLockSQL();
break;
if ($lockMode === false || $lockMode === LockMode::NONE) {
return $sql;
}

case LockMode::PESSIMISTIC_WRITE:
$sql .= ' ' . $this->platform->getWriteLockSQL();
break;
if ($lockMode === LockMode::PESSIMISTIC_READ) {
return $sql . ' ' . $this->platform->getReadLockSQL();
}

case LockMode::OPTIMISTIC:
foreach ($this->selectedClasses as $selectedClass) {
if ( ! $selectedClass['class']->isVersioned) {
throw \Doctrine\ORM\OptimisticLockException::lockFailed($selectedClass['class']->name);
}
}
break;
case LockMode::NONE:
break;
if ($lockMode === LockMode::PESSIMISTIC_WRITE) {
return $sql . ' ' . $this->platform->getWriteLockSQL();
}

default:
throw \Doctrine\ORM\Query\QueryException::invalidLockMode();
if ($lockMode !== LockMode::OPTIMISTIC) {
throw QueryException::invalidLockMode();
}

foreach ($this->selectedClasses as $selectedClass) {
if ( ! $selectedClass['class']->isVersioned) {
throw OptimisticLockException::lockFailed($selectedClass['class']->name);
}
}

Expand Down Expand Up @@ -998,12 +1025,15 @@ public function walkOrderByClause($orderByClause)
*/
public function walkOrderByItem($orderByItem)
{
$type = strtoupper($orderByItem->type);
$expr = $orderByItem->expression;
$sql = ($expr instanceof AST\Node)
? $expr->dispatch($this)
: $this->walkResultVariable($this->queryComponents[$expr]['token']['value']);

return $sql . ' ' . strtoupper($orderByItem->type);
$this->orderedColumnsMap[$sql] = $type;

return $sql . ' ' . $type;
}

/**
Expand Down
15 changes: 15 additions & 0 deletions tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1971,6 +1971,21 @@ public function testArithmeticPriority()
);
}

/**
* @group DDC-2475
*/
public function testOrderByClauseShouldReplaceOrderByRelationMapping()
{
$this->assertSqlGeneration(
'SELECT r, b FROM Doctrine\Tests\Models\Routing\RoutingRoute r JOIN r.bookings b',
'SELECT r0_.id AS id0, r1_.id AS id1, r1_.passengerName AS passengerName2 FROM RoutingRoute r0_ INNER JOIN RoutingRouteBooking r1_ ON r0_.id = r1_.route_id ORDER BY r1_.passengerName ASC'
);

$this->assertSqlGeneration(
'SELECT r, b FROM Doctrine\Tests\Models\Routing\RoutingRoute r JOIN r.bookings b ORDER BY b.passengerName DESC',
'SELECT r0_.id AS id0, r1_.id AS id1, r1_.passengerName AS passengerName2 FROM RoutingRoute r0_ INNER JOIN RoutingRouteBooking r1_ ON r0_.id = r1_.route_id ORDER BY r1_.passengerName DESC'
);
}
}

class MyAbsFunction extends \Doctrine\ORM\Query\AST\Functions\FunctionNode
Expand Down

0 comments on commit 753d63c

Please sign in to comment.