protected function doModifyLimitQuery($query, $limit, $offset = null)
{
if ($limit === null) {
return $query;
}
$start = $offset + 1;
$end = $offset + $limit;
// We'll find a SELECT or SELECT distinct and prepend TOP n to it
// Even if the TOP n is very large, the use of a CTE will
// allow the SQL Server query planner to optimize it so it doesn't
// actually scan the entire range covered by the TOP clause.
$selectPattern = '/^(\\s*SELECT\\s+(?:DISTINCT\\s+)?)(.*)$/im';
$replacePattern = sprintf('$1%s $2', "TOP {$end}");
$query = preg_replace($selectPattern, $replacePattern, $query);
if (stristr($query, "ORDER BY")) {
// Inner order by is not valid in SQL Server for our purposes
// unless it's in a TOP N subquery.
$query = $this->scrubInnerOrderBy($query);
}
// Build a new limited query around the original, using a CTE
return sprintf("WITH dctrn_cte AS (%s) " . "SELECT * FROM (" . "SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS doctrine_rownum FROM dctrn_cte" . ") AS doctrine_tbl " . "WHERE doctrine_rownum BETWEEN %d AND %d ORDER BY doctrine_rownum ASC", $query, $start, $end);
}