Skip to content

Commit

Permalink
support queries containing OFFSET after LIMIT (#178)
Browse files Browse the repository at this point in the history
Co-authored-by: Markus Staab <m.staab@complex-it.de>
  • Loading branch information
staabm and clxmstaab authored Jan 22, 2022
1 parent cbac599 commit 47d8cce
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 0 deletions.
41 changes: 41 additions & 0 deletions .phpstan-dba.cache

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 61 additions & 0 deletions .phpunit-phpstan-dba.cache

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions src/QueryReflection/QuerySimulation.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace staabm\PHPStanDba\QueryReflection;

use PHPStan\ShouldNotHappenException;
use PHPStan\Type\ArrayType;
use PHPStan\Type\BooleanType;
use PHPStan\Type\ConstantScalarType;
Expand Down Expand Up @@ -113,6 +114,13 @@ private static function stripTraillingLimit(string $queryString): ?string
{
$queryString = rtrim($queryString, ';');

// strip trailling OFFSET
$queryString = preg_replace('/(.*)OFFSET\s+["\']?\d+["\']?\s*$/i', '$1', $queryString);

if (null === $queryString) {
throw new ShouldNotHappenException('Could not strip trailing offset from query');
}

// XXX someday we will use a proper SQL parser,
// which would also allow us to support even more complex expressions like SELECT .. LIMIT X, Y FOR UPDATE
return preg_replace('/\s*LIMIT\s+["\']?\d+["\']?\s*(,\s*["\']?\d*["\']?)?\s*$/i', '', $queryString);
Expand Down
7 changes: 7 additions & 0 deletions tests/data/pdo.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,11 @@ public function placeholderInData(PDO $pdo)
$stmt = $pdo->query($query, PDO::FETCH_ASSOC);
assertType('PDOStatement<array{adaid: int<0, 4294967295>}>', $stmt);
}

public function offsetAfterLimit(PDO $pdo, int $limit, int $offset)
{
$query = 'SELECT adaid FROM ada LIMIT '.$limit.' OFFSET '.$offset;
$stmt = $pdo->query($query, PDO::FETCH_ASSOC);
assertType('PDOStatement<array{adaid: int<0, 4294967295>}>', $stmt);
}
}
38 changes: 38 additions & 0 deletions tests/data/syntax-error-in-prepared-statement.php
Original file line number Diff line number Diff line change
Expand Up @@ -208,4 +208,42 @@ public function noErrorInBug94(Connection $connection)
$orderId = 15315351;
$connection->preparedQuery($sql, ['orderId' => $orderId, 'productId' => $productId, 'supplierId' => $supplierId]);
}

public function noErrorOnBug175(Connection $connection, int $limit, int $offset)
{
$connection->preparedQuery('
SELECT email, adaid
FROM ada
WHERE gesperrt = ?
LIMIT ?
OFFSET '.$offset.'
', [1, $limit]);

$connection->preparedQuery('
SELECT email, adaid
FROM ada
WHERE gesperrt = ?
LIMIT ?
OFFSET '.((int) $offset).'
', [1, $limit]);
}

public function noErrorOnOffsetAfterLimit(Connection $connection, int $limit, int $offset)
{
$connection->preparedQuery('
SELECT email, adaid
FROM ada
WHERE gesperrt = ?
LIMIT ?
OFFSET ?
', [1, $limit, $offset]);

$connection->preparedQuery('
SELECT email, adaid
FROM ada
WHERE gesperrt = :gesperrt
LIMIT :limit
OFFSET :offset
', [':gesperrt' => 1, ':limit' => $limit, ':offset' => $offset]);
}
}

0 comments on commit 47d8cce

Please sign in to comment.