Skip to content

Commit 47d8cce

Browse files
staabmclxmstaab
andauthored
support queries containing OFFSET after LIMIT (#178)
Co-authored-by: Markus Staab <[email protected]>
1 parent cbac599 commit 47d8cce

File tree

5 files changed

+155
-0
lines changed

5 files changed

+155
-0
lines changed

.phpstan-dba.cache

Lines changed: 41 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.phpunit-phpstan-dba.cache

Lines changed: 61 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/QueryReflection/QuerySimulation.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace staabm\PHPStanDba\QueryReflection;
66

7+
use PHPStan\ShouldNotHappenException;
78
use PHPStan\Type\ArrayType;
89
use PHPStan\Type\BooleanType;
910
use PHPStan\Type\ConstantScalarType;
@@ -113,6 +114,13 @@ private static function stripTraillingLimit(string $queryString): ?string
113114
{
114115
$queryString = rtrim($queryString, ';');
115116

117+
// strip trailling OFFSET
118+
$queryString = preg_replace('/(.*)OFFSET\s+["\']?\d+["\']?\s*$/i', '$1', $queryString);
119+
120+
if (null === $queryString) {
121+
throw new ShouldNotHappenException('Could not strip trailing offset from query');
122+
}
123+
116124
// XXX someday we will use a proper SQL parser,
117125
// which would also allow us to support even more complex expressions like SELECT .. LIMIT X, Y FOR UPDATE
118126
return preg_replace('/\s*LIMIT\s+["\']?\d+["\']?\s*(,\s*["\']?\d*["\']?)?\s*$/i', '', $queryString);

tests/data/pdo.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,4 +163,11 @@ public function placeholderInData(PDO $pdo)
163163
$stmt = $pdo->query($query, PDO::FETCH_ASSOC);
164164
assertType('PDOStatement<array{adaid: int<0, 4294967295>}>', $stmt);
165165
}
166+
167+
public function offsetAfterLimit(PDO $pdo, int $limit, int $offset)
168+
{
169+
$query = 'SELECT adaid FROM ada LIMIT '.$limit.' OFFSET '.$offset;
170+
$stmt = $pdo->query($query, PDO::FETCH_ASSOC);
171+
assertType('PDOStatement<array{adaid: int<0, 4294967295>}>', $stmt);
172+
}
166173
}

tests/data/syntax-error-in-prepared-statement.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,4 +208,42 @@ public function noErrorInBug94(Connection $connection)
208208
$orderId = 15315351;
209209
$connection->preparedQuery($sql, ['orderId' => $orderId, 'productId' => $productId, 'supplierId' => $supplierId]);
210210
}
211+
212+
public function noErrorOnBug175(Connection $connection, int $limit, int $offset)
213+
{
214+
$connection->preparedQuery('
215+
SELECT email, adaid
216+
FROM ada
217+
WHERE gesperrt = ?
218+
LIMIT ?
219+
OFFSET '.$offset.'
220+
', [1, $limit]);
221+
222+
$connection->preparedQuery('
223+
SELECT email, adaid
224+
FROM ada
225+
WHERE gesperrt = ?
226+
LIMIT ?
227+
OFFSET '.((int) $offset).'
228+
', [1, $limit]);
229+
}
230+
231+
public function noErrorOnOffsetAfterLimit(Connection $connection, int $limit, int $offset)
232+
{
233+
$connection->preparedQuery('
234+
SELECT email, adaid
235+
FROM ada
236+
WHERE gesperrt = ?
237+
LIMIT ?
238+
OFFSET ?
239+
', [1, $limit, $offset]);
240+
241+
$connection->preparedQuery('
242+
SELECT email, adaid
243+
FROM ada
244+
WHERE gesperrt = :gesperrt
245+
LIMIT :limit
246+
OFFSET :offset
247+
', [':gesperrt' => 1, ':limit' => $limit, ':offset' => $offset]);
248+
}
211249
}

0 commit comments

Comments
 (0)