From 76d1f9331ce6e0d5cd7d7b6b6047ca0acb6460e4 Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Thu, 15 Sep 2016 17:28:44 -0700 Subject: [PATCH] Oracle platform ignores OFFSET in case if LIMIT is not specified --- .../DBAL/Platforms/OraclePlatform.php | 31 +++++++++++-------- .../DBAL/Functional/ModifyLimitQueryTest.php | 1 + .../DBAL/Platforms/OraclePlatformTest.php | 12 +++++++ 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/lib/Doctrine/DBAL/Platforms/OraclePlatform.php b/lib/Doctrine/DBAL/Platforms/OraclePlatform.php index 3aca7a89ecd..283c823cf99 100644 --- a/lib/Doctrine/DBAL/Platforms/OraclePlatform.php +++ b/lib/Doctrine/DBAL/Platforms/OraclePlatform.php @@ -977,24 +977,29 @@ public function getName() */ protected function doModifyLimitQuery($query, $limit, $offset = null) { - $limit = (int) $limit; - $offset = (int) $offset; + if ($limit === null && $offset === null) { + return $query; + } if (preg_match('/^\s*SELECT/i', $query)) { if (!preg_match('/\sFROM\s/i', $query)) { $query .= " FROM dual"; } - if ($limit > 0) { - $max = $offset + $limit; - $column = '*'; - if ($offset > 0) { - $min = $offset + 1; - $query = 'SELECT * FROM (SELECT a.' . $column . ', rownum AS doctrine_rownum FROM (' . - $query . - ') a WHERE rownum <= ' . $max . ') WHERE doctrine_rownum >= ' . $min; - } else { - $query = 'SELECT a.' . $column . ' FROM (' . $query . ') a WHERE ROWNUM <= ' . $max; - } + + $columns = array('a.*'); + + if ($offset > 0) { + $columns[] = 'ROWNUM AS doctrine_rownum'; + } + + $query = sprintf('SELECT %s FROM (%s) a', implode(', ', $columns), $query); + + if ($limit !== null) { + $query .= sprintf(' WHERE ROWNUM <= %d', $offset + $limit); + } + + if ($offset > 0) { + $query = sprintf('SELECT * FROM (%s) WHERE doctrine_rownum >= %d', $query, $offset + 1); } } diff --git a/tests/Doctrine/Tests/DBAL/Functional/ModifyLimitQueryTest.php b/tests/Doctrine/Tests/DBAL/Functional/ModifyLimitQueryTest.php index 0361d696d9b..b19af7a4f81 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/ModifyLimitQueryTest.php +++ b/tests/Doctrine/Tests/DBAL/Functional/ModifyLimitQueryTest.php @@ -42,6 +42,7 @@ public function testModifyLimitQuerySimpleQuery() $this->assertLimitResult(array(1, 2, 3, 4), $sql, 10, 0); $this->assertLimitResult(array(1, 2), $sql, 2, 0); $this->assertLimitResult(array(3, 4), $sql, 2, 2); + $this->assertLimitResult(array(2, 3, 4), $sql, null, 1); } public function testModifyLimitQueryJoinQuery() diff --git a/tests/Doctrine/Tests/DBAL/Platforms/OraclePlatformTest.php b/tests/Doctrine/Tests/DBAL/Platforms/OraclePlatformTest.php index db2d1fbd9bc..6ddbcdc63e8 100644 --- a/tests/Doctrine/Tests/DBAL/Platforms/OraclePlatformTest.php +++ b/tests/Doctrine/Tests/DBAL/Platforms/OraclePlatformTest.php @@ -263,6 +263,18 @@ public function testModifyLimitQueryWithEmptyOffset() $this->assertEquals('SELECT a.* FROM (SELECT * FROM user) a WHERE ROWNUM <= 10', $sql); } + public function testModifyLimitQueryWithNonEmptyOffset() + { + $sql = $this->_platform->modifyLimitQuery('SELECT * FROM user', 10, 10); + $this->assertEquals('SELECT * FROM (SELECT a.*, ROWNUM AS doctrine_rownum FROM (SELECT * FROM user) a WHERE ROWNUM <= 20) WHERE doctrine_rownum >= 11', $sql); + } + + public function testModifyLimitQueryWithEmptyLimit() + { + $sql = $this->_platform->modifyLimitQuery('SELECT * FROM user', null, 10); + $this->assertEquals('SELECT * FROM (SELECT a.*, ROWNUM AS doctrine_rownum FROM (SELECT * FROM user) a) WHERE doctrine_rownum >= 11', $sql); + } + public function testModifyLimitQueryWithAscOrderBy() { $sql = $this->_platform->modifyLimitQuery('SELECT * FROM user ORDER BY username ASC', 10);