Commit 26938877 authored by Bill Schaller's avatar Bill Schaller

Improved SQLServer2012Platform and tests per @stof's comments

parent 182e1fcb
...@@ -24,7 +24,8 @@ use Doctrine\DBAL\Schema\Sequence; ...@@ -24,7 +24,8 @@ use Doctrine\DBAL\Schema\Sequence;
/** /**
* Platform to ensure compatibility of Doctrine with Microsoft SQL Server 2012 version. * Platform to ensure compatibility of Doctrine with Microsoft SQL Server 2012 version.
* *
* Differences to SQL Server 2008 and before are that sequences are introduced. * Differences to SQL Server 2008 and before are that sequences are introduced,
* and support for the new OFFSET... FETCH syntax for result pagination has been added.
* *
* @author Steve Müller <st.mueller@dzh-online.de> * @author Steve Müller <st.mueller@dzh-online.de>
*/ */
...@@ -104,12 +105,11 @@ class SQLServer2012Platform extends SQLServer2008Platform ...@@ -104,12 +105,11 @@ class SQLServer2012Platform extends SQLServer2008Platform
} }
/** /**
* Adds SQL Server 2012 specific LIMIT clause to the query
* @inheritdoc * @inheritdoc
*/ */
protected function doModifyLimitQuery($query, $limit, $offset = NULL) protected function doModifyLimitQuery($query, $limit, $offset = null)
{ {
if($limit === null && $offset === null) { if ($limit === null && $offset === null) {
return $query; return $query;
} }
...@@ -123,16 +123,17 @@ class SQLServer2012Platform extends SQLServer2008Platform ...@@ -123,16 +123,17 @@ class SQLServer2012Platform extends SQLServer2008Platform
$query = substr_replace($query, ", @@version as dctrn_ver", $from, 0); $query = substr_replace($query, ", @@version as dctrn_ver", $from, 0);
} }
// This looks like MYSQL, but limit/offset are in inverse positions if ($offset === null) {
$offset = 0;
}
// This looks somewhat like MYSQL, but limit/offset are in inverse positions
// Supposedly SQL:2008 core standard. // Supposedly SQL:2008 core standard.
if ($offset !== null) { // Per TSQL spec, FETCH NEXT n ROWS ONLY is not valid without OFFSET n ROWS.
$query .= " OFFSET " . (int)$offset . " ROWS"; $query .= " OFFSET " . (int)$offset . " ROWS";
if ($limit !== null) {
$query .= " FETCH NEXT " . (int)$limit . " ROWS ONLY"; if ($limit !== null) {
} $query .= " FETCH NEXT " . (int)$limit . " ROWS ONLY";
} elseif ($limit !== null) {
// Can't have FETCH NEXT n ROWS ONLY without OFFSET n ROWS - per TSQL spec
$query .= " OFFSET 0 ROWS FETCH NEXT " . (int)$limit . " ROWS ONLY";
} }
return $query; return $query;
...@@ -145,17 +146,22 @@ class SQLServer2012Platform extends SQLServer2008Platform ...@@ -145,17 +146,22 @@ class SQLServer2012Platform extends SQLServer2008Platform
* @param int $pos position of previous FROM instance, if any * @param int $pos position of previous FROM instance, if any
* @return bool|int * @return bool|int
*/ */
protected function findOuterFrom($query, $pos = 0) private function findOuterFrom($query, $pos = 0)
{ {
$needle = " from "; $needle = " from ";
if(false === ($found = stripos($query, $needle, $pos))) if (false === ($found = stripos($query, $needle, $pos))) {
return false; return false;
}
$before = substr_count($query, "(", 0, $found) - substr_count($query, ")", 0, $found); $before = substr_count($query, "(", 0, $found) - substr_count($query, ")", 0, $found);
$after = substr_count($query, "(", $found + strlen($needle)) - substr_count($query, ")", $found + strlen($needle)); $after = substr_count($query, "(", $found + strlen($needle)) - substr_count(
$query,
")",
$found + strlen($needle)
);
// $needle was found outside any parens. // $needle was found outside any parens.
if(!$before && !$after) { if (!$before && !$after) {
return $found; return $found;
} }
return $this->findOuterFrom($query, $found + strlen($needle)); return $this->findOuterFrom($query, $found + strlen($needle));
......
...@@ -58,10 +58,6 @@ class SQLServer2012PlatformTest extends AbstractSQLServerPlatformTestCase ...@@ -58,10 +58,6 @@ class SQLServer2012PlatformTest extends AbstractSQLServerPlatformTestCase
public function testModifyLimitQueryWithOffset() public function testModifyLimitQueryWithOffset()
{ {
if ( ! $this->_platform->supportsLimitOffset()) {
$this->markTestSkipped(sprintf('Platform "%s" does not support offsets in result limiting.', $this->_platform->getName()));
}
$sql = $this->_platform->modifyLimitQuery('SELECT * FROM user ORDER BY username DESC', 10, 5); $sql = $this->_platform->modifyLimitQuery('SELECT * FROM user ORDER BY username DESC', 10, 5);
$this->assertEquals('SELECT * FROM user ORDER BY username DESC OFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY', $sql); $this->assertEquals('SELECT * FROM user ORDER BY username DESC OFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY', $sql);
} }
...@@ -107,10 +103,6 @@ class SQLServer2012PlatformTest extends AbstractSQLServerPlatformTestCase ...@@ -107,10 +103,6 @@ class SQLServer2012PlatformTest extends AbstractSQLServerPlatformTestCase
public function testModifyLimitQueryWithSubSelectAndMultipleOrder() public function testModifyLimitQueryWithSubSelectAndMultipleOrder()
{ {
if ( ! $this->_platform->supportsLimitOffset()) {
$this->markTestSkipped(sprintf('Platform "%s" does not support offsets in result limiting.', $this->_platform->getName()));
}
$sql = $this->_platform->modifyLimitQuery('SELECT * FROM (SELECT u.id as uid, u.name as uname) dctrn_result ORDER BY uname DESC, uid ASC', 10, 5); $sql = $this->_platform->modifyLimitQuery('SELECT * FROM (SELECT u.id as uid, u.name as uname) dctrn_result ORDER BY uname DESC, uid ASC', 10, 5);
$this->assertEquals('SELECT * FROM (SELECT u.id as uid, u.name as uname) dctrn_result ORDER BY uname DESC, uid ASC OFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY', $sql); $this->assertEquals('SELECT * FROM (SELECT u.id as uid, u.name as uname) dctrn_result ORDER BY uname DESC, uid ASC OFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY', $sql);
...@@ -154,10 +146,6 @@ class SQLServer2012PlatformTest extends AbstractSQLServerPlatformTestCase ...@@ -154,10 +146,6 @@ class SQLServer2012PlatformTest extends AbstractSQLServerPlatformTestCase
*/ */
public function testModifyLimitQueryWithOrderByClause() public function testModifyLimitQueryWithOrderByClause()
{ {
if ( ! $this->_platform->supportsLimitOffset()) {
$this->markTestSkipped(sprintf('Platform "%s" does not support offsets in result limiting.', $this->_platform->getName()));
}
$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'; $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 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 OFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY'; $expected = '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 OFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY';
$actual = $this->_platform->modifyLimitQuery($sql, 10, 5); $actual = $this->_platform->modifyLimitQuery($sql, 10, 5);
...@@ -200,10 +188,6 @@ class SQLServer2012PlatformTest extends AbstractSQLServerPlatformTestCase ...@@ -200,10 +188,6 @@ class SQLServer2012PlatformTest extends AbstractSQLServerPlatformTestCase
*/ */
public function testModifyLimitQueryWithSubSelectInSelectListAndOrderByClause() public function testModifyLimitQueryWithSubSelectInSelectListAndOrderByClause()
{ {
if ( ! $this->_platform->supportsLimitOffset()) {
$this->markTestSkipped(sprintf('Platform "%s" does not support offsets in result limiting.', $this->_platform->getName()));
}
$sql = $this->_platform->modifyLimitQuery( $sql = $this->_platform->modifyLimitQuery(
"SELECT " . "SELECT " .
"u.id, " . "u.id, " .
......
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