diff --git a/lib/Cake/Model/Datasource/Database/Sqlserver.php b/lib/Cake/Model/Datasource/Database/Sqlserver.php index 71ebd21bb..32bc68f6e 100644 --- a/lib/Cake/Model/Datasource/Database/Sqlserver.php +++ b/lib/Cake/Model/Datasource/Database/Sqlserver.php @@ -114,6 +114,8 @@ class Sqlserver extends DboSource { */ private $__lastQueryHadError = false; + const ROW_COUNTER = '_cake_page_rownum_'; + /** * Connects to the database using options in the given configuration array. * @@ -522,13 +524,14 @@ class Sqlserver extends DboSource { $order = 'ORDER BY (SELECT NULL)'; } + $rowCounter = self::ROW_COUNTER; $pagination = " SELECT {$limit} * FROM ( - SELECT {$fields}, ROW_NUMBER() OVER ({$order}) AS ssma\$rownum + SELECT {$fields}, ROW_NUMBER() OVER ({$order}) AS {$rowCounter} FROM {$table} {$alias} {$joins} {$conditions} {$group} - ) AS ssma\$sub1 - WHERE ssma\$sub1.[ssma\$rownum] > {$limit2} - ORDER BY ssma\$sub1.[ssma\$rownum] + ) AS _cake_paging_ + WHERE _cake_paging_.{$rowCounter} > {$limit2} + ORDER BY _cake_paging_.{$rowCounter} "; return $pagination; } else { @@ -602,7 +605,8 @@ class Sqlserver extends DboSource { } /** - * Fetches the next row from the current result set + * Fetches the next row from the current result set. + * Eats the magic ROW_COUNTER variable. * * @return mixed */ @@ -611,6 +615,9 @@ class Sqlserver extends DboSource { $resultRow = array(); foreach ($this->map as $col => $meta) { list($table, $column, $type) = $meta; + if ($table === 0 && $column === self::ROW_COUNTER) { + continue; + } $resultRow[$table][$column] = $row[$col]; if ($type === 'boolean' && !is_null($row[$col])) { $resultRow[$table][$column] = $this->boolean($resultRow[$table][$column]); diff --git a/lib/Cake/Test/Case/Model/Datasource/Database/SqlserverTest.php b/lib/Cake/Test/Case/Model/Datasource/Database/SqlserverTest.php index e2ae5adad..57d82d07c 100644 --- a/lib/Cake/Test/Case/Model/Datasource/Database/SqlserverTest.php +++ b/lib/Cake/Test/Case/Model/Datasource/Database/SqlserverTest.php @@ -170,19 +170,6 @@ class SqlserverTestModel extends Model { public function find($conditions = null, $fields = null, $order = null, $recursive = null) { return $conditions; } - -/** - * findAll method - * - * @param mixed $conditions - * @param mixed $fields - * @param mixed $order - * @param mixed $recursive - * @return array - */ - public function findAll($conditions = null, $fields = null, $order = null, $recursive = null) { - return $conditions; - } } /** @@ -259,7 +246,7 @@ class SqlserverTest extends CakeTestCase { * * @var array */ - public $fixtures = array('core.category'); + public $fixtures = array('core.category', 'core.post'); /** * Sets up a Dbo class instance for testing @@ -575,4 +562,34 @@ class SqlserverTest extends CakeTestCase { ); $this->assertEqual($expected, $result); } + +/** + * SQL server < 11 doesn't have proper limit/offset support, test that our hack works. + * + * @return void + */ + public function testLimitOffsetHack() { + $this->loadFixtures('Post'); + $query = array( + 'limit' => 1, + 'page' => 1, + 'order' => 'Post.title ASC', + ); + $Post = ClassRegistry::init('Post'); + $results = $Post->find('all', $query); + + $this->assertEquals(1, count($results)); + $this->assertEquals('First Post', $results[0]['Post']['title']); + + $query = array( + 'limit' => 1, + 'page' => 2, + 'order' => 'Post.title ASC', + ); + $Post = ClassRegistry::init('Post'); + $results = $Post->find('all', $query); + $this->assertEquals(1, count($results)); + $this->assertFalse(isset($results[0][0])); + $this->assertEquals('Second Post', $results[0]['Post']['title']); + } }