Skip to content
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