Skip to content

Commit 31bd221

Browse files
committed
drivers: applyLimit throws exception for negative values (BC break)
1 parent fc24991 commit 31bd221

14 files changed

+83
-56
lines changed

src/Database/Drivers/MsSqlDriver.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ public function applyLimit(& $sql, $limit, $offset)
8080
if ($offset) {
8181
throw new Nette\NotSupportedException('Offset is not supported by this database.');
8282

83+
} elseif ($limit < 0) {
84+
throw new Nette\InvalidArgumentException('Negative offset or limit.');
85+
8386
} elseif ($limit !== NULL) {
8487
$sql = preg_replace('#^\s*(SELECT(\s+DISTINCT|\s+ALL)?|UPDATE|DELETE)#i', '$0 TOP ' . (int) $limit, $sql, 1, $count);
8588
if (!$count) {

src/Database/Drivers/MySqlDriver.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,13 @@ public function formatLike($value, $pos)
122122
*/
123123
public function applyLimit(& $sql, $limit, $offset)
124124
{
125-
if ($limit !== NULL || $offset > 0) {
125+
if ($limit < 0 || $offset < 0) {
126+
throw new Nette\InvalidArgumentException('Negative offset or limit.');
127+
128+
} elseif ($limit !== NULL || $offset) {
126129
// see http://dev.mysql.com/doc/refman/5.0/en/select.html
127130
$sql .= ' LIMIT ' . ($limit === NULL ? '18446744073709551615' : (int) $limit)
128-
. ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
131+
. ($offset ? ' OFFSET ' . (int) $offset : '');
129132
}
130133
}
131134

src/Database/Drivers/OciDriver.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,10 @@ public function formatLike($value, $pos)
101101
*/
102102
public function applyLimit(& $sql, $limit, $offset)
103103
{
104-
if ($offset > 0) {
104+
if ($limit < 0 || $offset < 0) {
105+
throw new Nette\InvalidArgumentException('Negative offset or limit.');
106+
107+
} elseif ($offset) {
105108
// see http://www.oracle.com/technology/oramag/oracle/06-sep/o56asktom.html
106109
$sql = 'SELECT * FROM (SELECT t.*, ROWNUM AS "__rnum" FROM (' . $sql . ') t '
107110
. ($limit !== NULL ? 'WHERE ROWNUM <= ' . ((int) $offset + (int) $limit) : '')

src/Database/Drivers/OdbcDriver.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ public function applyLimit(& $sql, $limit, $offset)
7979
if ($offset) {
8080
throw new Nette\NotSupportedException('Offset is not supported by this database.');
8181

82+
} elseif ($limit < 0) {
83+
throw new Nette\InvalidArgumentException('Negative offset or limit.');
84+
8285
} elseif ($limit !== NULL) {
8386
$sql = preg_replace('#^\s*(SELECT(\s+DISTINCT|\s+ALL)?|UPDATE|DELETE)#i', '$0 TOP ' . (int) $limit, $sql, 1, $count);
8487
if (!$count) {

src/Database/Drivers/PgSqlDriver.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,13 @@ public function formatLike($value, $pos)
106106
*/
107107
public function applyLimit(& $sql, $limit, $offset)
108108
{
109+
if ($limit < 0 || $offset < 0) {
110+
throw new Nette\InvalidArgumentException('Negative offset or limit.');
111+
}
109112
if ($limit !== NULL) {
110113
$sql .= ' LIMIT ' . (int) $limit;
111114
}
112-
if ($offset > 0) {
115+
if ($offset) {
113116
$sql .= ' OFFSET ' . (int) $offset;
114117
}
115118
}

src/Database/Drivers/SqliteDriver.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,12 @@ public function formatLike($value, $pos)
112112
*/
113113
public function applyLimit(& $sql, $limit, $offset)
114114
{
115-
if ($limit !== NULL || $offset > 0) {
115+
if ($limit < 0 || $offset < 0) {
116+
throw new Nette\InvalidArgumentException('Negative offset or limit.');
117+
118+
} elseif ($limit !== NULL || $offset) {
116119
$sql .= ' LIMIT ' . ($limit === NULL ? '-1' : (int) $limit)
117-
. ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
120+
. ($offset ? ' OFFSET ' . (int) $offset : '');
118121
}
119122
}
120123

src/Database/Drivers/SqlsrvDriver.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,10 @@ public function formatLike($value, $pos)
9292
*/
9393
public function applyLimit(& $sql, $limit, $offset)
9494
{
95-
if (version_compare($this->version, 11, '<')) { // 11 == SQL Server 2012
95+
if ($limit < 0 || $offset < 0) {
96+
throw new Nette\InvalidArgumentException('Negative offset or limit.');
97+
98+
} elseif (version_compare($this->version, 11, '<')) { // 11 == SQL Server 2012
9699
if ($offset) {
97100
throw new Nette\NotSupportedException('Offset is not supported by this database.');
98101

@@ -103,7 +106,7 @@ public function applyLimit(& $sql, $limit, $offset)
103106
}
104107
}
105108

106-
} elseif ($limit !== NULL || $offset > 0) {
109+
} elseif ($limit !== NULL || $offset) {
107110
// requires ORDER BY, see https://technet.microsoft.com/en-us/library/gg699618(v=sql.110).aspx
108111
$sql .= ' OFFSET ' . (int) $offset . ' ROWS '
109112
. 'FETCH NEXT ' . (int) $limit . ' ROWS ONLY';

tests/Database/Drivers/MsSqlDriver.applyLimit.phpt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@ Assert::exception(function () use ($driver) {
4747
$driver->applyLimit($query, 10, NULL);
4848
}, Nette\InvalidArgumentException::class, 'SQL query must begin with SELECT, UPDATE or DELETE command.');
4949

50-
$query = 'SELECT 1 FROM t';
51-
$driver->applyLimit($query, -1, NULL);
52-
Assert::same('SELECT TOP -1 1 FROM t', $query);
50+
Assert::exception(function () use ($driver) {
51+
$query = 'SELECT 1 FROM t';
52+
$driver->applyLimit($query, -1, NULL);
53+
}, Nette\InvalidArgumentException::class, 'Negative offset or limit.');
5354

5455
Assert::exception(function () use ($driver) {
5556
$query = 'SELECT 1 FROM t';

tests/Database/Drivers/MySqlDriver.applyLimit.phpt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@ $query = 'SELECT 1 FROM t';
3131
$driver->applyLimit($query, 10, NULL);
3232
Assert::same('SELECT 1 FROM t LIMIT 10', $query);
3333

34-
$query = 'SELECT 1 FROM t';
35-
$driver->applyLimit($query, -1, NULL);
36-
Assert::same('SELECT 1 FROM t LIMIT -1', $query);
37-
38-
$query = 'SELECT 1 FROM t';
39-
$driver->applyLimit($query, NULL, -1);
40-
Assert::same('SELECT 1 FROM t', $query);
34+
Assert::exception(function () use ($driver) {
35+
$query = 'SELECT 1 FROM t';
36+
$driver->applyLimit($query, -1, NULL);
37+
}, Nette\InvalidArgumentException::class, 'Negative offset or limit.');
38+
39+
Assert::exception(function () use ($driver) {
40+
$query = 'SELECT 1 FROM t';
41+
$driver->applyLimit($query, NULL, -1);
42+
}, Nette\InvalidArgumentException::class, 'Negative offset or limit.');

tests/Database/Drivers/OciDriver.applyLimit.phpt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@ $query = 'SELECT 1 FROM t';
2727
$driver->applyLimit($query, 10, NULL);
2828
Assert::same('SELECT * FROM (SELECT 1 FROM t) WHERE ROWNUM <= 10', $query);
2929

30-
$query = 'SELECT 1 FROM t';
31-
$driver->applyLimit($query, -1, NULL);
32-
Assert::same('SELECT * FROM (SELECT 1 FROM t) WHERE ROWNUM <= -1', $query);
33-
34-
$query = 'SELECT 1 FROM t';
35-
$driver->applyLimit($query, NULL, -1);
36-
Assert::same('SELECT 1 FROM t', $query);
30+
Assert::exception(function () use ($driver) {
31+
$query = 'SELECT 1 FROM t';
32+
$driver->applyLimit($query, -1, NULL);
33+
}, Nette\InvalidArgumentException::class, 'Negative offset or limit.');
34+
35+
Assert::exception(function () use ($driver) {
36+
$query = 'SELECT 1 FROM t';
37+
$driver->applyLimit($query, NULL, -1);
38+
}, Nette\InvalidArgumentException::class, 'Negative offset or limit.');

tests/Database/Drivers/OdbcDriver.applyLimit.phpt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@ Assert::exception(function () use ($driver) {
4747
$driver->applyLimit($query, 10, NULL);
4848
}, Nette\InvalidArgumentException::class, 'SQL query must begin with SELECT, UPDATE or DELETE command.');
4949

50-
$query = 'SELECT 1 FROM t';
51-
$driver->applyLimit($query, -1, NULL);
52-
Assert::same('SELECT TOP -1 1 FROM t', $query);
50+
Assert::exception(function () use ($driver) {
51+
$query = 'SELECT 1 FROM t';
52+
$driver->applyLimit($query, -1, NULL);
53+
}, Nette\InvalidArgumentException::class, 'Negative offset or limit.');
5354

5455
Assert::exception(function () use ($driver) {
5556
$query = 'SELECT 1 FROM t';

tests/Database/Drivers/PgSqlDriver.applyLimit.phpt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@ $query = 'SELECT 1 FROM t';
2727
$driver->applyLimit($query, 10, NULL);
2828
Assert::same('SELECT 1 FROM t LIMIT 10', $query);
2929

30-
$query = 'SELECT 1 FROM t';
31-
$driver->applyLimit($query, -1, NULL);
32-
Assert::same('SELECT 1 FROM t LIMIT -1', $query);
33-
34-
$query = 'SELECT 1 FROM t';
35-
$driver->applyLimit($query, NULL, -1);
36-
Assert::same('SELECT 1 FROM t', $query);
30+
Assert::exception(function () use ($driver) {
31+
$query = 'SELECT 1 FROM t';
32+
$driver->applyLimit($query, -1, NULL);
33+
}, Nette\InvalidArgumentException::class, 'Negative offset or limit.');
34+
35+
Assert::exception(function () use ($driver) {
36+
$query = 'SELECT 1 FROM t';
37+
$driver->applyLimit($query, NULL, -1);
38+
}, Nette\InvalidArgumentException::class, 'Negative offset or limit.');

tests/Database/Drivers/SqliteDriver.applyLimit.phpt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@ $query = 'SELECT 1 FROM t';
2727
$driver->applyLimit($query, 10, NULL);
2828
Assert::same('SELECT 1 FROM t LIMIT 10', $query);
2929

30-
$query = 'SELECT 1 FROM t';
31-
$driver->applyLimit($query, -1, NULL);
32-
Assert::same('SELECT 1 FROM t LIMIT -1', $query);
33-
34-
$query = 'SELECT 1 FROM t';
35-
$driver->applyLimit($query, NULL, -1);
36-
Assert::same('SELECT 1 FROM t', $query);
30+
Assert::exception(function () use ($driver) {
31+
$query = 'SELECT 1 FROM t';
32+
$driver->applyLimit($query, -1, NULL);
33+
}, Nette\InvalidArgumentException::class, 'Negative offset or limit.');
34+
35+
Assert::exception(function () use ($driver) {
36+
$query = 'SELECT 1 FROM t';
37+
$driver->applyLimit($query, NULL, -1);
38+
}, Nette\InvalidArgumentException::class, 'Negative offset or limit.');

tests/Database/Drivers/SqlsrvDriver.applyLimit.phpt

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,6 @@ Assert::exception(function () use ($driver) {
4848
$driver->applyLimit($query, 10, NULL);
4949
}, Nette\InvalidArgumentException::class, 'SQL query must begin with SELECT, UPDATE or DELETE command.');
5050

51-
$query = 'SELECT 1 FROM t';
52-
$driver->applyLimit($query, -1, NULL);
53-
Assert::same('SELECT TOP -1 1 FROM t', $query);
54-
55-
Assert::exception(function () use ($driver) {
56-
$query = 'SELECT 1 FROM t';
57-
$driver->applyLimit($query, NULL, -1);
58-
}, Nette\NotSupportedException::class, 'Offset is not supported by this database.');
5951

6052

6153
$version = $rc->getProperty('version');
@@ -82,10 +74,14 @@ $query = 'SELECT 1 FROM t';
8274
$driver->applyLimit($query, 10, NULL);
8375
Assert::same('SELECT 1 FROM t OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY', $query);
8476

85-
$query = 'SELECT 1 FROM t';
86-
$driver->applyLimit($query, -1, NULL);
87-
Assert::same('SELECT 1 FROM t OFFSET 0 ROWS FETCH NEXT -1 ROWS ONLY', $query);
8877

89-
$query = 'SELECT 1 FROM t';
90-
$driver->applyLimit($query, NULL, -1);
91-
Assert::same('SELECT 1 FROM t', $query);
78+
79+
Assert::exception(function () use ($driver) {
80+
$query = 'SELECT 1 FROM t';
81+
$driver->applyLimit($query, -1, NULL);
82+
}, Nette\InvalidArgumentException::class, 'Negative offset or limit.');
83+
84+
Assert::exception(function () use ($driver) {
85+
$query = 'SELECT 1 FROM t';
86+
$driver->applyLimit($query, NULL, -1);
87+
}, Nette\InvalidArgumentException::class, 'Negative offset or limit.');

0 commit comments

Comments
 (0)