Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Report invalid query after simulation as unresolvable #551

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
16 changes: 9 additions & 7 deletions src/QueryReflection/QueryReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
use staabm\PHPStanDba\SchemaReflection\SchemaReflection;
use staabm\PHPStanDba\SqlAst\ParserInference;
use staabm\PHPStanDba\UnresolvableQueryException;
use staabm\PHPStanDba\UnresolvableQueryDynamicFromException;

final class QueryReflection
{
Expand Down Expand Up @@ -291,13 +292,7 @@ public function resolveQueryStrings(Expr $queryExpr, Scope $scope): iterable

$queryString = $this->resolveQueryExpr($queryExpr, $scope);
if (null !== $queryString) {
$normalizedQuery = QuerySimulation::stripComments($this->normalizeQueryString($queryString));

// query simulation might lead in a invalid query, skip those
$error = $this->validateQueryString($normalizedQuery);
if ($error === null) {
yield $normalizedQuery;
}
yield QuerySimulation::stripComments($this->normalizeQueryString($queryString));
}
}

Expand Down Expand Up @@ -375,6 +370,13 @@ private function resolveQueryStringExpr(Expr $queryExpr, Scope $scope, bool $res
return null;
}

// queries with a dynamic FROM are not resolvable
if (QueryReflection::getRuntimeConfiguration()->isDebugEnabled()) {
if (str_ends_with(rtrim($leftString), 'FROM') && is_numeric(trim($rightString, '"\''))) {
throw new UnresolvableQueryDynamicFromException('Seems the query is too dynamic to be resolved by query simulation');
}
}

return $leftString . $rightString;
}

Expand Down
16 changes: 16 additions & 0 deletions src/UnresolvableQueryDynamicFromException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace staabm\PHPStanDba;

/**
* @api
*/
final class UnresolvableQueryDynamicFromException extends UnresolvableQueryException
{
public static function getTip(): string
{
return 'Consider to simplify the FROM-clause construction.';
}
}
8 changes: 8 additions & 0 deletions tests/rules/SyntaxErrorInQueryMethodRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ public function testSyntaxErrorInQueryRule(): void
"Query error: Table 'phpstan_dba.adasfd' doesn't exist (1146).",
138,
],
[
"Query error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL/MariaDB server version for the right syntax to use near 'WHERE adaid = 1' at line 1 (1064).",
155,
],
[
"Query error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL/MariaDB server version for the right syntax to use near 'WHERE adaid = 1' at line 1 (1064).",
156,
],
];
} elseif (PdoMysqlQueryReflector::NAME === getenv('DBA_REFLECTOR')) {
$expected = [
Expand Down
17 changes: 15 additions & 2 deletions tests/rules/UnresolvableQueryMethodRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use PHPStan\Testing\RuleTestCase;
use staabm\PHPStanDba\QueryReflection\QueryReflection;
use staabm\PHPStanDba\Rules\SyntaxErrorInQueryMethodRule;
use staabm\PHPStanDba\UnresolvableQueryDynamicFromException;
use staabm\PHPStanDba\UnresolvableQueryMixedTypeException;
use staabm\PHPStanDba\UnresolvableQueryStringTypeException;

Expand Down Expand Up @@ -71,12 +72,24 @@ public function testBug536(): void

public function testBug548(): void
{
$this->analyse([__DIR__ . '/data/bug-548.php'], []);
$this->analyse([__DIR__ . '/data/bug-548.php'], [
[
'Unresolvable Query: Seems the query is too dynamic to be resolved by query simulation.',
10,
UnresolvableQueryDynamicFromException::getTip(),
],
]);
}

public function testBug547(): void
{
$this->analyse([__DIR__ . '/data/bug-547.php'], []);
$this->analyse([__DIR__ . '/data/bug-547.php'], [
[
'Unresolvable Query: Seems the query is too dynamic to be resolved by query simulation.',
10,
UnresolvableQueryDynamicFromException::getTip(),
],
]);
}

public function testBug676(): void
Expand Down
8 changes: 8 additions & 0 deletions tests/rules/data/syntax-error-in-query-method.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,12 @@ public function bug458(PDO $pdo)
$pdo->query('SELECT * FROM ' . $table . ' LIMIT 1');
}

public function writes(PDO $pdo, int $adaid): void
{
$pdo->query('UPDATE `ada` SET email="test" WHERE adaid = '.$adaid);
$pdo->query('INSERT INTO `ada` SET email="test" WHERE adaid = '.$adaid);
$pdo->query('REPLACE INTO `ada` SET email="test" WHERE adaid = '.$adaid);
$pdo->query('DELETE FROM `ada` WHERE adaid = '.$adaid);
}

}
8 changes: 8 additions & 0 deletions tests/rules/data/unresolvable-query-in-method.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,12 @@ public function stringQueryFragment(PDO $pdo, string $string)
{
$pdo->query('SELECT email FROM ada WHERE '.$string);
}

public function writes(PDO $pdo, int $adaid): void
{
$pdo->query('UPDATE `ada` SET email="test" WHERE adaid = '.$adaid);
$pdo->query('INSERT INTO `ada` SET email="test" WHERE adaid = '.$adaid);
$pdo->query('REPLACE INTO `ada` SET email="test" WHERE adaid = '.$adaid);
$pdo->query('DELETE FROM `ada` WHERE adaid = '.$adaid);
}
}
Loading