Unverified Commit ff92ad64 authored by Sergei Morozov's avatar Sergei Morozov

Merge pull request #3248 from morozov/non-nullable-offset

Made the OFFSET in LIMIT queries non-nullable integer defaulting to 0
parents 4e92005c 254f38f1
# Upgrade to 3.0 # Upgrade to 3.0
## BC BREAK: The `NULL` value of `$offset` in LIMIT queries is not allowed
The `NULL` value of the `$offset` argument in `AbstractPlatform::(do)?ModifyLimitQuery()` methods is no longer allowed. The absence of the offset should be indicated with a `0` which is now the default value.
## BC BREAK: Removed dbal:import CLI command ## BC BREAK: Removed dbal:import CLI command
The `dbal:import` CLI command has been removed since it only worked with PDO-based drivers by relying on a non-documented behavior of the extension, and it was impossible to make it work with other drivers. The `dbal:import` CLI command has been removed since it only worked with PDO-based drivers by relying on a non-documented behavior of the extension, and it was impossible to make it work with other drivers.
......
...@@ -3340,22 +3340,10 @@ abstract class AbstractPlatform ...@@ -3340,22 +3340,10 @@ abstract class AbstractPlatform
/** /**
* Adds an driver-specific LIMIT clause to the query. * Adds an driver-specific LIMIT clause to the query.
* *
* @param string $query
* @param int|null $limit
* @param int|null $offset
*
* @return string
*
* @throws DBALException * @throws DBALException
*/ */
final public function modifyLimitQuery($query, $limit, $offset = null) final public function modifyLimitQuery(string $query, ?int $limit, int $offset = 0) : string
{ {
if ($limit !== null) {
$limit = (int) $limit;
}
$offset = (int) $offset;
if ($offset < 0) { if ($offset < 0) {
throw new DBALException(sprintf( throw new DBALException(sprintf(
'Offset must be a positive integer or zero, %d given', 'Offset must be a positive integer or zero, %d given',
...@@ -3375,21 +3363,15 @@ abstract class AbstractPlatform ...@@ -3375,21 +3363,15 @@ abstract class AbstractPlatform
/** /**
* Adds an platform-specific LIMIT clause to the query. * Adds an platform-specific LIMIT clause to the query.
*
* @param string $query
* @param int|null $limit
* @param int|null $offset
*
* @return string
*/ */
protected function doModifyLimitQuery($query, $limit, $offset) protected function doModifyLimitQuery(string $query, ?int $limit, int $offset) : string
{ {
if ($limit !== null) { if ($limit !== null) {
$query .= ' LIMIT ' . $limit; $query .= sprintf(' LIMIT %d', $limit);
} }
if ($offset > 0) { if ($offset > 0) {
$query .= ' OFFSET ' . $offset; $query .= sprintf(' OFFSET %d', $offset);
} }
return $query; return $query;
......
...@@ -782,7 +782,7 @@ class DB2Platform extends AbstractPlatform ...@@ -782,7 +782,7 @@ class DB2Platform extends AbstractPlatform
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function doModifyLimitQuery($query, $limit, $offset = null) protected function doModifyLimitQuery(string $query, ?int $limit, int $offset) : string
{ {
$where = []; $where = [];
......
...@@ -47,7 +47,7 @@ class MySqlPlatform extends AbstractPlatform ...@@ -47,7 +47,7 @@ class MySqlPlatform extends AbstractPlatform
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function doModifyLimitQuery($query, $limit, $offset) protected function doModifyLimitQuery(string $query, ?int $limit, int $offset) : string
{ {
if ($limit !== null) { if ($limit !== null) {
$query .= ' LIMIT ' . $limit; $query .= ' LIMIT ' . $limit;
......
...@@ -971,7 +971,7 @@ SQL ...@@ -971,7 +971,7 @@ SQL
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function doModifyLimitQuery($query, $limit, $offset = null) protected function doModifyLimitQuery(string $query, ?int $limit, int $offset) : string
{ {
if ($limit === null && $offset <= 0) { if ($limit === null && $offset <= 0) {
return $query; return $query;
......
...@@ -1352,16 +1352,16 @@ SQL ...@@ -1352,16 +1352,16 @@ SQL
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
protected function doModifyLimitQuery($query, $limit, $offset) protected function doModifyLimitQuery(string $query, ?int $limit, int $offset) : string
{ {
$limitOffsetClause = ''; $limitOffsetClause = '';
if ($limit > 0) { if ($limit !== null) {
$limitOffsetClause = 'TOP ' . $limit . ' '; $limitOffsetClause = 'TOP ' . $limit . ' ';
} }
if ($offset > 0) { if ($offset > 0) {
if ($limit === 0) { if ($limit === null) {
$limitOffsetClause = 'TOP ALL '; $limitOffsetClause = 'TOP ALL ';
} }
......
...@@ -6,6 +6,7 @@ use Doctrine\DBAL\Schema\Sequence; ...@@ -6,6 +6,7 @@ use Doctrine\DBAL\Schema\Sequence;
use const PREG_OFFSET_CAPTURE; use const PREG_OFFSET_CAPTURE;
use function preg_match; use function preg_match;
use function preg_match_all; use function preg_match_all;
use function sprintf;
use function substr_count; use function substr_count;
/** /**
...@@ -92,7 +93,7 @@ class SQLServer2012Platform extends SQLServerPlatform ...@@ -92,7 +93,7 @@ class SQLServer2012Platform extends SQLServerPlatform
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
protected function doModifyLimitQuery($query, $limit, $offset = null) protected function doModifyLimitQuery(string $query, ?int $limit, int $offset) : string
{ {
if ($limit === null && $offset <= 0) { if ($limit === null && $offset <= 0) {
return $query; return $query;
...@@ -125,17 +126,13 @@ class SQLServer2012Platform extends SQLServerPlatform ...@@ -125,17 +126,13 @@ class SQLServer2012Platform extends SQLServerPlatform
} }
} }
if ($offset === null) {
$offset = 0;
}
// This looks somewhat like MYSQL, but limit/offset are in inverse positions // This looks somewhat like MYSQL, but limit/offset are in inverse positions
// Supposedly SQL:2008 core standard. // Supposedly SQL:2008 core standard.
// Per TSQL spec, FETCH NEXT n ROWS ONLY is not valid without OFFSET n ROWS. // Per TSQL spec, FETCH NEXT n ROWS ONLY is not valid without OFFSET n ROWS.
$query .= ' OFFSET ' . (int) $offset . ' ROWS'; $query .= sprintf(' OFFSET %d ROWS', $offset);
if ($limit !== null) { if ($limit !== null) {
$query .= ' FETCH NEXT ' . (int) $limit . ' ROWS ONLY'; $query .= sprintf(' FETCH NEXT %d ROWS ONLY', $limit);
} }
return $query; return $query;
......
...@@ -1237,7 +1237,7 @@ SQL ...@@ -1237,7 +1237,7 @@ SQL
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function doModifyLimitQuery($query, $limit, $offset = null) protected function doModifyLimitQuery(string $query, ?int $limit, int $offset) : string
{ {
$where = []; $where = [];
......
...@@ -689,10 +689,10 @@ class SqlitePlatform extends AbstractPlatform ...@@ -689,10 +689,10 @@ class SqlitePlatform extends AbstractPlatform
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function doModifyLimitQuery($query, $limit, $offset) protected function doModifyLimitQuery(string $query, ?int $limit, int $offset) : string
{ {
if ($limit === null && $offset > 0) { if ($limit === null && $offset > 0) {
return $query . ' LIMIT -1 OFFSET ' . $offset; $limit = -1;
} }
return parent::doModifyLimitQuery($query, $limit, $offset); return parent::doModifyLimitQuery($query, $limit, $offset);
......
...@@ -342,7 +342,7 @@ class DB2PlatformTest extends AbstractPlatformTestCase ...@@ -342,7 +342,7 @@ class DB2PlatformTest extends AbstractPlatformTestCase
{ {
self::assertEquals( self::assertEquals(
'SELECT * FROM user', 'SELECT * FROM user',
$this->platform->modifyLimitQuery('SELECT * FROM user', null, null) $this->platform->modifyLimitQuery('SELECT * FROM user', null, 0)
); );
self::assertEquals( self::assertEquals(
......
...@@ -760,7 +760,7 @@ class SQLAnywherePlatformTest extends AbstractPlatformTestCase ...@@ -760,7 +760,7 @@ class SQLAnywherePlatformTest extends AbstractPlatformTestCase
); );
self::assertEquals( self::assertEquals(
'SELECT TOP ALL START AT 6 * FROM user', 'SELECT TOP ALL START AT 6 * FROM user',
$this->platform->modifyLimitQuery('SELECT * FROM user', 0, 5) $this->platform->modifyLimitQuery('SELECT * FROM user', null, 5)
); );
} }
......
...@@ -53,7 +53,7 @@ class SQLServerPlatformTest extends AbstractSQLServerPlatformTestCase ...@@ -53,7 +53,7 @@ class SQLServerPlatformTest extends AbstractSQLServerPlatformTestCase
[ [
'SELECT id_0, MIN(sclr_2) AS dctrn_minrownum FROM (SELECT c0_.id AS id_0, c0_.title AS title_1, ROW_NUMBER() OVER(ORDER BY c0_.title ASC) AS sclr_2 FROM TestTable c0_ ORDER BY c0_.title ASC) dctrn_result GROUP BY id_0 ORDER BY dctrn_minrownum ASC', 'SELECT id_0, MIN(sclr_2) AS dctrn_minrownum FROM (SELECT c0_.id AS id_0, c0_.title AS title_1, ROW_NUMBER() OVER(ORDER BY c0_.title ASC) AS sclr_2 FROM TestTable c0_ ORDER BY c0_.title ASC) dctrn_result GROUP BY id_0 ORDER BY dctrn_minrownum ASC',
30, 30,
null, 0,
'WITH dctrn_cte AS (SELECT TOP 30 id_0, MIN(sclr_2) AS dctrn_minrownum FROM (SELECT c0_.id AS id_0, c0_.title AS title_1, ROW_NUMBER() OVER(ORDER BY c0_.title ASC) AS sclr_2 FROM TestTable c0_) dctrn_result GROUP BY id_0 ORDER BY dctrn_minrownum ASC) SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS doctrine_rownum FROM dctrn_cte) AS doctrine_tbl WHERE doctrine_rownum <= 30 ORDER BY doctrine_rownum ASC', 'WITH dctrn_cte AS (SELECT TOP 30 id_0, MIN(sclr_2) AS dctrn_minrownum FROM (SELECT c0_.id AS id_0, c0_.title AS title_1, ROW_NUMBER() OVER(ORDER BY c0_.title ASC) AS sclr_2 FROM TestTable c0_) dctrn_result GROUP BY id_0 ORDER BY dctrn_minrownum ASC) SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS doctrine_rownum FROM dctrn_cte) AS doctrine_tbl WHERE doctrine_rownum <= 30 ORDER BY doctrine_rownum ASC',
], ],
...@@ -61,7 +61,7 @@ class SQLServerPlatformTest extends AbstractSQLServerPlatformTestCase ...@@ -61,7 +61,7 @@ class SQLServerPlatformTest extends AbstractSQLServerPlatformTestCase
[ [
'SELECT id_0, MIN(sclr_2) AS dctrn_minrownum FROM (SELECT c0_.id AS id_0, c0_.title AS title_1, ROW_NUMBER() OVER(ORDER BY c0_.title ASC) AS sclr_2 FROM TestTable c0_) dctrn_result GROUP BY id_0 ORDER BY dctrn_minrownum ASC', 'SELECT id_0, MIN(sclr_2) AS dctrn_minrownum FROM (SELECT c0_.id AS id_0, c0_.title AS title_1, ROW_NUMBER() OVER(ORDER BY c0_.title ASC) AS sclr_2 FROM TestTable c0_) dctrn_result GROUP BY id_0 ORDER BY dctrn_minrownum ASC',
30, 30,
null, 0,
'WITH dctrn_cte AS (SELECT TOP 30 id_0, MIN(sclr_2) AS dctrn_minrownum FROM (SELECT c0_.id AS id_0, c0_.title AS title_1, ROW_NUMBER() OVER(ORDER BY c0_.title ASC) AS sclr_2 FROM TestTable c0_) dctrn_result GROUP BY id_0 ORDER BY dctrn_minrownum ASC) SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS doctrine_rownum FROM dctrn_cte) AS doctrine_tbl WHERE doctrine_rownum <= 30 ORDER BY doctrine_rownum ASC', 'WITH dctrn_cte AS (SELECT TOP 30 id_0, MIN(sclr_2) AS dctrn_minrownum FROM (SELECT c0_.id AS id_0, c0_.title AS title_1, ROW_NUMBER() OVER(ORDER BY c0_.title ASC) AS sclr_2 FROM TestTable c0_) dctrn_result GROUP BY id_0 ORDER BY dctrn_minrownum ASC) SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS doctrine_rownum FROM dctrn_cte) AS doctrine_tbl WHERE doctrine_rownum <= 30 ORDER BY doctrine_rownum ASC',
], ],
]; ];
......
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