Commit 5a8eedf6 authored by Guilherme Blanco's avatar Guilherme Blanco

Merge pull request #332 from FabioBatSilva/DDC-2470

[DDC-2470, DDC-2441] Use column name instead of alias to modify order by clause
parents da9564df 6e8ee199
...@@ -802,58 +802,63 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -802,58 +802,63 @@ class SQLServerPlatform extends AbstractPlatform
*/ */
protected function doModifyLimitQuery($query, $limit, $offset = null) protected function doModifyLimitQuery($query, $limit, $offset = null)
{ {
if ($limit > 0) { if ($limit === null) {
$orderby = stristr($query, 'ORDER BY'); return $query;
//Remove ORDER BY from $query }
$query = preg_replace('/\s+ORDER\s+BY\s+([^\)]*)/', '', $query);
$over = 'ORDER BY';
if ( ! $orderby) {
$over .= ' (SELECT 0)';
} else {
//Clear ORDER BY
$orderby = preg_replace('/ORDER\s+BY\s+([^\)]*)(.*)/', '$1', $orderby);
$orderbyParts = explode(',', $orderby);
$orderbyColumns = array();
//Split ORDER BY into parts
foreach ($orderbyParts as &$part) {
$part = trim($part);
if (preg_match('/(([^\s]*)\.)?([^\.\s]*)\s*(ASC|DESC)?/i', $part, $matches)) {
$orderbyColumns[] = array(
'table' => empty($matches[2]) ? '[^\.\s]*' : $matches[2],
'column' => $matches[3],
'sort' => isset($matches[4]) ? $matches[4] : null
);
}
}
//Find alias for each colum used in ORDER BY $start = $offset + 1;
if (count($orderbyColumns)) { $end = $offset + $limit;
foreach ($orderbyColumns as $column) { $orderBy = stristr($query, 'ORDER BY');
if (preg_match('/' . $column['table'] . '\.(' . $column['column'] . ')\s*(AS)?\s*([^,\s\)]*)/i', $query, $matches)) { $query = preg_replace('/\s+ORDER\s+BY\s+([^\)]*)/', '', $query); //Remove ORDER BY from $query
$over .= ' ' . $matches[3]; $format = 'SELECT * FROM (%s) AS doctrine_tbl WHERE doctrine_rownum BETWEEN %d AND %d';
$over .= isset($column['sort']) ? ' ' . $column['sort'] . ',' : ',';
} else { if ( ! $orderBy) {
$over .= ' ' . $column['column']; //Replace only first occurrence of FROM with OVER to prevent changing FROM also in subqueries.
$over .= isset($column['sort']) ? ' ' . $column['sort'] . ',' : ','; $query = preg_replace('/\sFROM\s/i', ', ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS doctrine_rownum FROM ', $query, 1);
}
} return sprintf($format, $query, $start, $end);
}
$over = rtrim($over, ',');
} //Clear ORDER BY
$orderBy = preg_replace('/ORDER\s+BY\s+([^\)]*)(.*)/', '$1', $orderBy);
$orderByParts = explode(',', $orderBy);
$orderbyColumns = array();
//Split ORDER BY into parts
foreach ($orderByParts as &$part) {
if (preg_match('/(([^\s]*)\.)?([^\.\s]*)\s*(ASC|DESC)?/i', trim($part), $matches)) {
$orderbyColumns[] = array(
'column' => $matches[3],
'hasTable' => ( ! empty($matches[2])),
'sort' => isset($matches[4]) ? $matches[4] : null,
'table' => empty($matches[2]) ? '[^\.\s]*' : $matches[2]
);
} }
}
//Find alias for each colum used in ORDER BY
if ( ! empty($orderbyColumns)) {
foreach ($orderbyColumns as $column) {
//Replace only first occurrence of FROM with $over to prevent changing FROM also in subqueries. $pattern = sprintf('/%s\.(%s)\s*(AS)?\s*([^,\s\)]*)/i', $column['table'], $column['column']);
$query = preg_replace('/\sFROM\s/i', ", ROW_NUMBER() OVER ($over) AS doctrine_rownum FROM ", $query, 1); $overColumn = preg_match($pattern, $query, $matches)
? ($column['hasTable'] ? $column['table'] . '.' : '') . $column['column']
: $column['column'];
$start = $offset + 1; if (isset($column['sort'])) {
$end = $offset + $limit; $overColumn .= ' ' . $column['sort'];
}
$query = "SELECT * FROM ($query) AS doctrine_tbl WHERE doctrine_rownum BETWEEN $start AND $end"; $overColumns[] = $overColumn;
}
} }
return $query; //Replace only first occurrence of FROM with $over to prevent changing FROM also in subqueries.
$over = 'ORDER BY ' . implode(', ', $overColumns);
$query = preg_replace('/\sFROM\s/i', ", ROW_NUMBER() OVER ($over) AS doctrine_rownum FROM ", $query, 1);
return sprintf($format, $query, $start, $end);
} }
/** /**
......
...@@ -204,16 +204,16 @@ class SQLServerPlatformTest extends AbstractPlatformTestCase ...@@ -204,16 +204,16 @@ class SQLServerPlatformTest extends AbstractPlatformTestCase
public function testModifyLimitQueryWithSubSelectAndOrder() public function testModifyLimitQueryWithSubSelectAndOrder()
{ {
$sql = $this->_platform->modifyLimitQuery('SELECT * FROM (SELECT u.id as uid, u.name as uname ORDER BY u.name DESC) dctrn_result', 10); $sql = $this->_platform->modifyLimitQuery('SELECT * FROM (SELECT u.id as uid, u.name as uname ORDER BY u.name DESC) dctrn_result', 10);
$this->assertEquals('SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY uname DESC) AS doctrine_rownum FROM (SELECT u.id as uid, u.name as uname) dctrn_result) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 1 AND 10', $sql); $this->assertEquals('SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY u.name DESC) AS doctrine_rownum FROM (SELECT u.id as uid, u.name as uname) dctrn_result) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 1 AND 10', $sql);
} }
public function testModifyLimitQueryWithSubSelectAndMultipleOrder() public function testModifyLimitQueryWithSubSelectAndMultipleOrder()
{ {
$sql = $this->_platform->modifyLimitQuery('SELECT * FROM (SELECT u.id as uid, u.name as uname ORDER BY u.name DESC, id ASC) dctrn_result', 10, 5); $sql = $this->_platform->modifyLimitQuery('SELECT * FROM (SELECT u.id as uid, u.name as uname ORDER BY u.name DESC, id ASC) dctrn_result', 10, 5);
$this->assertEquals('SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY uname DESC, uid ASC) AS doctrine_rownum FROM (SELECT u.id as uid, u.name as uname) dctrn_result) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 6 AND 15', $sql); $this->assertEquals('SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY u.name DESC, id ASC) AS doctrine_rownum FROM (SELECT u.id as uid, u.name as uname) dctrn_result) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 6 AND 15', $sql);
$sql = $this->_platform->modifyLimitQuery('SELECT * FROM (SELECT u.id uid, u.name uname ORDER BY u.name DESC, id ASC) dctrn_result', 10, 5); $sql = $this->_platform->modifyLimitQuery('SELECT * FROM (SELECT u.id uid, u.name uname ORDER BY u.name DESC, id ASC) dctrn_result', 10, 5);
$this->assertEquals('SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY uname DESC, uid ASC) AS doctrine_rownum FROM (SELECT u.id uid, u.name uname) dctrn_result) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 6 AND 15', $sql); $this->assertEquals('SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY u.name DESC, id ASC) AS doctrine_rownum FROM (SELECT u.id uid, u.name uname) dctrn_result) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 6 AND 15', $sql);
} }
public function testModifyLimitQueryWithFromColumnNames() public function testModifyLimitQueryWithFromColumnNames()
...@@ -221,6 +221,18 @@ class SQLServerPlatformTest extends AbstractPlatformTestCase ...@@ -221,6 +221,18 @@ class SQLServerPlatformTest extends AbstractPlatformTestCase
$sql = $this->_platform->modifyLimitQuery('SELECT a.fromFoo, fromBar FROM foo', 10); $sql = $this->_platform->modifyLimitQuery('SELECT a.fromFoo, fromBar FROM foo', 10);
$this->assertEquals('SELECT * FROM (SELECT a.fromFoo, fromBar, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS doctrine_rownum FROM foo) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 1 AND 10', $sql); $this->assertEquals('SELECT * FROM (SELECT a.fromFoo, fromBar, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS doctrine_rownum FROM foo) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 1 AND 10', $sql);
} }
/**
* @group DDC-2470
*/
public function testModifyLimitQueryWithOrderByClause()
{
$sql = 'SELECT m0_.NOMBRE AS NOMBRE0, m0_.FECHAINICIO AS FECHAINICIO1, m0_.FECHAFIN AS FECHAFIN2 FROM MEDICION m0_ WITH (NOLOCK) INNER JOIN ESTUDIO e1_ ON m0_.ESTUDIO_ID = e1_.ID INNER JOIN CLIENTE c2_ ON e1_.CLIENTE_ID = c2_.ID INNER JOIN USUARIO u3_ ON c2_.ID = u3_.CLIENTE_ID WHERE u3_.ID = ? ORDER BY m0_.FECHAINICIO DESC';
$expected = 'SELECT * FROM (SELECT m0_.NOMBRE AS NOMBRE0, m0_.FECHAINICIO AS FECHAINICIO1, m0_.FECHAFIN AS FECHAFIN2, ROW_NUMBER() OVER (ORDER BY m0_.FECHAINICIO DESC) AS doctrine_rownum FROM MEDICION m0_ WITH (NOLOCK) INNER JOIN ESTUDIO e1_ ON m0_.ESTUDIO_ID = e1_.ID INNER JOIN CLIENTE c2_ ON e1_.CLIENTE_ID = c2_.ID INNER JOIN USUARIO u3_ ON c2_.ID = u3_.CLIENTE_ID WHERE u3_.ID = ?) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 6 AND 15';
$actual = $this->_platform->modifyLimitQuery($sql, 10, 5);
$this->assertEquals($expected, $actual);
}
/** /**
* @group DDC-1360 * @group DDC-1360
......
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