Commit be2c7033 authored by Steve Müller's avatar Steve Müller Committed by Benjamin Eberlei

fix modifying limit and offset for statements with subqueries on SQL Server

parent 1b90a2eb
...@@ -809,9 +809,17 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -809,9 +809,17 @@ class SQLServerPlatform extends AbstractPlatform
$query = preg_replace('/\s+ORDER\s+BY\s+([^\)]*)/', '', $query); //Remove ORDER BY from $query $query = preg_replace('/\s+ORDER\s+BY\s+([^\)]*)/', '', $query); //Remove ORDER BY from $query
$format = 'SELECT * FROM (%s) AS doctrine_tbl WHERE doctrine_rownum BETWEEN %d AND %d'; $format = 'SELECT * FROM (%s) AS doctrine_tbl WHERE doctrine_rownum BETWEEN %d AND %d';
// Pattern to match "main" SELECT ... FROM clause (including nested parentheses in select list).
$selectFromPattern = '/^(\s*SELECT\s+(?:\((?>[^()]+)|(?:R)*\)|[^(])+)\sFROM\s/i';
if ( ! $orderBy) { if ( ! $orderBy) {
//Replace only first occurrence of FROM with OVER to prevent changing FROM also in subqueries. //Replace only "main" FROM with OVER to prevent changing FROM also in subqueries.
$query = preg_replace('/\sFROM\s/i', ', ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS doctrine_rownum FROM ', $query, 1); $query = preg_replace(
$selectFromPattern,
'$1, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS doctrine_rownum FROM ',
$query,
1
);
return sprintf($format, $query, $start, $end); return sprintf($format, $query, $start, $end);
} }
...@@ -853,7 +861,7 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -853,7 +861,7 @@ class SQLServerPlatform extends AbstractPlatform
//Replace only first occurrence of FROM with $over to prevent changing FROM also in subqueries. //Replace only first occurrence of FROM with $over to prevent changing FROM also in subqueries.
$over = 'ORDER BY ' . implode(', ', $overColumns); $over = 'ORDER BY ' . implode(', ', $overColumns);
$query = preg_replace('/\sFROM\s/i', ", ROW_NUMBER() OVER ($over) AS doctrine_rownum FROM ", $query, 1); $query = preg_replace($selectFromPattern, "$1, ROW_NUMBER() OVER ($over) AS doctrine_rownum FROM ", $query, 1);
return sprintf($format, $query, $start, $end); return sprintf($format, $query, $start, $end);
} }
......
...@@ -102,6 +102,20 @@ class ModifyLimitQueryTest extends \Doctrine\Tests\DbalFunctionalTestCase ...@@ -102,6 +102,20 @@ class ModifyLimitQueryTest extends \Doctrine\Tests\DbalFunctionalTestCase
$this->assertLimitResult(array(2), $sql, 1, 1); $this->assertLimitResult(array(2), $sql, 1, 1);
} }
public function testModifyLimitQuerySubSelect()
{
$this->_conn->insert('modify_limit_table', array('test_int' => 1));
$this->_conn->insert('modify_limit_table', array('test_int' => 2));
$this->_conn->insert('modify_limit_table', array('test_int' => 3));
$this->_conn->insert('modify_limit_table', array('test_int' => 4));
$sql = "SELECT *, (SELECT COUNT(*) FROM modify_limit_table) AS cnt FROM modify_limit_table";
$this->assertLimitResult(array(4, 3, 2, 1), $sql, 10, 0, false);
$this->assertLimitResult(array(4, 3), $sql, 2, 0, false);
$this->assertLimitResult(array(2, 1), $sql, 2, 2, false);
}
public function assertLimitResult($expectedResults, $sql, $limit, $offset, $deterministic = true) public function assertLimitResult($expectedResults, $sql, $limit, $offset, $deterministic = true)
{ {
$p = $this->_conn->getDatabasePlatform(); $p = $this->_conn->getDatabasePlatform();
......
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