Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions src/Query/SqlWalker.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ class SqlWalker
*/
public const HINT_PARTIAL = 'doctrine.partial';

/**
* Used to prevent nested ORDER BY statements which cause an exception in SQL Server
*/
public const HINT_DISABLE_COLLECTION_ORDER_BY = 'doctrine.disableCollectionOrderBy';

private readonly ResultSetMapping $rsm;

/**
Expand Down Expand Up @@ -511,9 +516,11 @@ protected function createSqlForFinalizer(AST\SelectStatement $selectStatement):
$sql .= $this->walkOrderByClause($selectStatement->orderByClause);
}

$orderBySql = $this->generateOrderedCollectionOrderByItems();
if (! $selectStatement->orderByClause && $orderBySql) {
$sql .= ' ORDER BY ' . $orderBySql;
if (! $this->query->getHint(self::HINT_DISABLE_COLLECTION_ORDER_BY)) {
$orderBySql = $this->generateOrderedCollectionOrderByItems();
if (!$selectStatement->orderByClause && $orderBySql) {
$sql .= ' ORDER BY ' . $orderBySql;
}
}

$this->assertOptimisticLockingHasAllClassesVersioned();
Expand Down
5 changes: 5 additions & 0 deletions src/Tools/Pagination/CountOutputWalker.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Doctrine\ORM\Query\ParserResult;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\ORM\Query\SqlOutputWalker;
use Doctrine\ORM\Query\SqlWalker;
use RuntimeException;

use function array_diff;
Expand Down Expand Up @@ -56,6 +57,10 @@ public function __construct(Query $query, ParserResult $parserResult, array $que
protected function createSqlForFinalizer(SelectStatement $selectStatement): string
{
if ($this->platform instanceof SQLServerPlatform) {
// disable collection‑based ORDER BY for the inner select
$query = $this->getQuery();
$query->setHint(SqlWalker::HINT_DISABLE_COLLECTION_ORDER_BY, true);
// preserve original clearing also that is only partially sufficient
$selectStatement->orderByClause = null;
}

Expand Down
6 changes: 6 additions & 0 deletions src/Tools/Pagination/LimitSubqueryOutputWalker.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use Doctrine\ORM\Query\QueryException;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\ORM\Query\SqlOutputWalker;
use Doctrine\ORM\Query\SqlWalker;
use LogicException;
use RuntimeException;

Expand Down Expand Up @@ -103,6 +104,11 @@ public function __construct(
$this->maxResults = $cloneQuery->getMaxResults();
$cloneQuery->setFirstResult(0)->setMaxResults(null);

if ($this->platform instanceof SQLServerPlatform) {
// disable collection‑based ORDER BY for the inner select
$cloneQuery->setHint(SqlWalker::HINT_DISABLE_COLLECTION_ORDER_BY, true);
}

$this->em = $cloneQuery->getEntityManager();
$this->quoteStrategy = $this->em->getConfiguration()->getQuoteStrategy();

Expand Down
8 changes: 8 additions & 0 deletions src/Tools/Pagination/Paginator.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Internal\SQLResultCasing;
use Doctrine\ORM\NoResultException;
use Doctrine\DBAL\Platforms\SQLServerPlatform;
use Doctrine\ORM\Query;
use Doctrine\ORM\Query\Parameter;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\ORM\Query\SqlWalker;
use Doctrine\ORM\QueryBuilder;
use IteratorAggregate;
use Traversable;
Expand Down Expand Up @@ -122,6 +124,12 @@ public function getIterator(): Traversable
$this->unbindUnusedQueryParams($subQuery);
}

// disable collection ordering for SQL Server
$platform = $subQuery->getEntityManager()->getConnection()->getDatabasePlatform();
if ($platform instanceof SQLServerPlatform) {
$subQuery->setHint(SqlWalker::HINT_DISABLE_COLLECTION_ORDER_BY, true);
}

$subQuery->setFirstResult($offset)->setMaxResults($length);

$foundIdRows = $subQuery->getScalarResult();
Expand Down