diff options
author | Andrey Andreev <narf@bofh.bg> | 2012-06-11 15:12:43 +0200 |
---|---|---|
committer | Andrey Andreev <narf@bofh.bg> | 2012-06-11 15:12:43 +0200 |
commit | 71379ca89226fe8af0314a8b70e5dc0f57367255 (patch) | |
tree | 7a2356481098652dec85b4810be3fab13d4363b6 /system/database/drivers | |
parent | ba2617646eb072be0ecfec8818e332345010fc03 (diff) |
Add OFFSET support for SQL Server 2005+ in MSSQL/SQLSRV
Diffstat (limited to 'system/database/drivers')
-rw-r--r-- | system/database/drivers/mssql/mssql_driver.php | 25 | ||||
-rw-r--r-- | system/database/drivers/sqlsrv/sqlsrv_driver.php | 25 |
2 files changed, 46 insertions, 4 deletions
diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php index 87094e76e..47dc55844 100644 --- a/system/database/drivers/mssql/mssql_driver.php +++ b/system/database/drivers/mssql/mssql_driver.php @@ -504,7 +504,30 @@ class CI_DB_mssql_driver extends CI_DB { */ protected function _limit($sql, $limit, $offset) { - return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.($limit + $offset).' ', $sql); + // As of SQL Server 2012 (11.0.*) OFFSET is supported + if (version_compare($this->version(), '11', '>=')) + { + return $sql.' OFFSET '.(int) $offset.' ROWS FETCH NEXT '.(int) $limit.' ROWS ONLY'; + } + + $limit = $offset + $limit; + + // As of SQL Server 2005 (9.0.*) ROW_NUMBER() is supported, + // however an ORDER BY clause is required for it to work + if (version_compare($this->version(), '9', '>=') && $offset && ! empty($this->qb_orderby)) + { + $orderby = 'ORDER BY '.implode(', ', $this->qb_orderby); + + // We have to strip the ORDER BY clause + $sql = trim(substr($sql, 0, strrpos($sql, 'ORDER BY '.$orderby))); + + return 'SELECT '.(count($this->qb_select) === 0 ? '*' : implode(', ', $this->qb_select))." FROM (\n" + .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.$orderby.') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) + ."\n) ".$this->escape_identifiers('CI_subquery') + ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.((int) $offset + 1).' AND '.$limit; + } + + return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql); } // -------------------------------------------------------------------- diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php index eebd6bff8..825c02452 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_driver.php +++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php @@ -463,9 +463,28 @@ class CI_DB_sqlsrv_driver extends CI_DB { protected function _limit($sql, $limit, $offset) { // As of SQL Server 2012 (11.0.*) OFFSET is supported - return version_compare($this->version(), '11', '>=') - ? $sql.' OFFSET '.(int) $offset.' ROWS FETCH NEXT '.(int) $limit.' ROWS ONLY' - : preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.($limit + $offset).' ', $sql); + if (version_compare($this->version(), '11', '>=')) + { + return $sql.' OFFSET '.(int) $offset.' ROWS FETCH NEXT '.(int) $limit.' ROWS ONLY'; + } + + $limit = $offset + $limit; + + // An ORDER BY clause is required for ROW_NUMBER() to work + if ($offset && ! empty($this->qb_orderby)) + { + $orderby = 'ORDER BY '.implode(', ', $this->qb_orderby); + + // We have to strip the ORDER BY clause + $sql = trim(substr($sql, 0, strrpos($sql, 'ORDER BY '.$orderby))); + + return 'SELECT '.(count($this->qb_select) === 0 ? '*' : implode(', ', $this->qb_select))." FROM (\n" + .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.$orderby.') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) + ."\n) ".$this->escape_identifiers('CI_subquery') + ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.((int) $offset + 1).' AND '.$limit; + } + + return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql); } // -------------------------------------------------------------------- |