From 39f9161cc4d2e3d4a6f299dffa142c707de9b86f Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Thu, 7 Aug 2025 12:01:02 +0300 Subject: [PATCH 1/9] staticcall --- .phpstan-dba-mysqli.cache | 250 +----------------- composer.json | 5 +- src/Rules/QueryPlanAnalyzerRule.php | 16 +- ...ntaxErrorInPreparedStatementMethodRule.php | 14 +- src/Rules/SyntaxErrorInQueryMethodRule.php | 33 ++- tests/default/Fixture/StaticDatabase.php | 28 ++ .../config/.phpunit-phpstan-dba-mysqli.cache | 8 - tests/rules/QueryPlanAnalyzerRuleTest.php | 41 +-- ...ErrorInPreparedStatementMethodRuleTest.php | 30 +++ .../SyntaxErrorInQueryMethodRuleTest.php | 33 ++- .../config/.phpunit-phpstan-dba-mysqli.cache | 34 ++- tests/rules/data/query-plan-analyzer.php | 6 + .../syntax-error-in-prepared-statement.php | 6 + .../data/syntax-error-in-query-method.php | 5 + .../config/.phpunit-phpstan-dba-mysqli.cache | 50 ++-- 15 files changed, 239 insertions(+), 320 deletions(-) create mode 100644 tests/default/Fixture/StaticDatabase.php diff --git a/.phpstan-dba-mysqli.cache b/.phpstan-dba-mysqli.cache index 853efb155..e295303a4 100644 --- a/.phpstan-dba-mysqli.cache +++ b/.phpstan-dba-mysqli.cache @@ -1,6 +1,6 @@ 'v12-new-cache5', - 'schemaHash' => 'f94fe2b38e193ad685009d3f4942f476', + 'schemaHash' => 'cc7b87e840d13ff393d87083b544963d', 'records' => array ( 'SELECT @@ -46,102 +46,10 @@ array ( 5 => array ( - 'type-description' => 'array{dbsignature: string|null, 0: string|null, grouper: int, 1: int}', - ), - 3 => - array ( - 'type-description' => 'array{dbsignature: string|null, grouper: int}', - ), - ), - ), - 'SELECT * FROM ada' => - array ( - 'result' => - array ( - 3 => - array ( - 'type-description' => 'array{adaid: int<-32768, 32767>, gesperrt: int<-128, 127>, email: string, freigabe1u1: int<-32768, 32767>}', - ), - ), - ), - 'SELECT * FROM ak' => - array ( - 'result' => - array ( - 3 => - array ( - 'type-description' => 'array{akid: int<-2147483648, 2147483647>, eladaid: int<-2147483648, 2147483647>|null, eadavk: numeric-string}', - ), - ), - ), - 'SELECT adaid FROM ada WHERE adaid IN (\'1\')' => - array ( - 'result' => - array ( - 5 => - array ( - 'type-description' => 'array{adaid: int<-32768, 32767>, 0: int<-32768, 32767>}', - ), - ), - ), - 'SELECT adaid FROM ada WHERE adaid IN (\'1\') AND email LIKE \'1970-01-01\'' => - array ( - 'result' => - array ( - 5 => - array ( - 'type-description' => 'array{adaid: int<-32768, 32767>, 0: int<-32768, 32767>}', - ), - ), - ), - 'SELECT adaid FROM ada WHERE email LIKE \'%questions ?%\'' => - array ( - 'result' => - array ( - 5 => - array ( - 'type-description' => 'array{adaid: int<-32768, 32767>, 0: int<-32768, 32767>}', + 'type-description' => 'array{dbsignature: string|null, 0: string|null, grouper: int<-2147483648, 2147483647>, 1: int<-2147483648, 2147483647>}', ), ), ), - 'SELECT adaid FROM ada WHERE email LIKE \'hello?%\'' => - array ( - 'result' => - array ( - 5 => - array ( - 'type-description' => 'array{adaid: int<-32768, 32767>, 0: int<-32768, 32767>}', - ), - ), - ), - 'SELECT akid FROM ak WHERE akid IN (\'1\')' => - array ( - 'result' => - array ( - 5 => - array ( - 'type-description' => 'array{akid: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', - ), - ), - ), - 'SELECT akid FROM ak WHERE id IN (\'1\')' => - array ( - 'error' => - \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'id\' in \'where clause\'', - 'code' => 1054, - )), - ), - 'SELECT akid FROM table WHERE id IN (\'1\')' => - array ( - 'error' => - \staabm\PHPStanDba\Error::__set_state(array( - 'message' => '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 \'table WHERE id IN (\'1\') LIMIT 0\' at line 1 - -Simulated query: SELECT akid FROM table WHERE id IN (\'1\') LIMIT 0', - 'code' => 1064, - )), - ), 'SELECT column_name, column_default, is_nullable FROM information_schema.columns WHERE table_name = \'1970-01-01\'' => @@ -150,162 +58,10 @@ Simulated query: SELECT akid FROM table WHERE id IN (\'1\') LIMIT 0', array ( 5 => array ( - 'type-description' => 'array{COLUMN_NAME: string|null, 0: string|null, COLUMN_DEFAULT: string|null, 1: string|null, IS_NULLABLE: string, 2: string}', - ), - ), - ), - 'SELECT email adaid - WHERE gesperrt = \'1\' AND email LIKE \'%@example.com\' - FROM ada - LIMIT 1' => - array ( - 'error' => - \staabm\PHPStanDba\Error::__set_state(array( - 'message' => '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 \'FROM ada LIMIT 0\' at line 3 - -Simulated query: SELECT email adaid - WHERE gesperrt = \'1\' AND email LIKE \'%@example.com\' - FROM ada LIMIT 0', - 'code' => 1064, - )), - ), - 'SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada' => - array ( - 'error' => - \staabm\PHPStanDba\Error::__set_state(array( - 'message' => '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 \'freigabe1u1 FROM ada LIMIT 0\' at line 1 - -Simulated query: SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada LIMIT 0', - 'code' => 1064, - )), - ), - 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => - array ( - 'error' => - \staabm\PHPStanDba\Error::__set_state(array( - 'message' => '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 \'gesperrt freigabe1u1 FROM ada LIMIT 0\' at line 1 - -Simulated query: SELECT email adaid gesperrt freigabe1u1 FROM ada LIMIT 0', - 'code' => 1064, - )), - ), - 'SELECT email, adaid FROM ada WHERE email = \'a\'' => - array ( - 'result' => - array ( - 5 => - array ( - 'type-description' => 'array{email: string, 0: string, adaid: int<-32768, 32767>, 1: int<-32768, 32767>}', - ), - ), - ), - 'SELECT email, adaid FROM ada' => - array ( - 'result' => - array ( - 5 => - array ( - 'type-description' => 'array{email: string, 0: string, adaid: int<-32768, 32767>, 1: int<-32768, 32767>}', - ), - ), - ), - 'SELECT email, adaid FROM ada WHERE adaid = \'1\'' => - array ( - 'result' => - array ( - 5 => - array ( - 'type-description' => 'array{email: string, 0: string, adaid: int<-32768, 32767>, 1: int<-32768, 32767>}', - ), - ), - ), - 'SELECT email, adaid FROM ada WHERE adaid=1' => - array ( - 'result' => - array ( - 5 => - array ( - 'type-description' => 'array{email: string, 0: string, adaid: int<-32768, 32767>, 1: int<-32768, 32767>}', - ), - ), - ), - 'SELECT email, adaid FROM ada WHERE email = \'test@example.org\'' => - array ( - 'result' => - array ( - 5 => - array ( - 'type-description' => 'array{email: string, 0: string, adaid: int<-32768, 32767>, 1: int<-32768, 32767>}', + 'type-description' => 'array{column_name: string, 0: string, column_default: string|null, 1: string|null, is_nullable: string, 2: string}', ), ), ), - 'SELECT email, adaid FROM ada WHERE email=\'test@example.org\'' => - array ( - 'result' => - array ( - 5 => - array ( - 'type-description' => 'array{email: string, 0: string, adaid: int<-32768, 32767>, 1: int<-32768, 32767>}', - ), - ), - ), - 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE adaid = \'1\'' => - array ( - 'result' => - array ( - 5 => - array ( - 'type-description' => 'array{email: string, 0: string, adaid: int<-32768, 32767>, 1: int<-32768, 32767>, gesperrt: int<-128, 127>, 2: int<-128, 127>, freigabe1u1: int<-32768, 32767>, 3: int<-32768, 32767>}', - ), - ), - ), - 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE asdsa=\'1\'' => - array ( - 'error' => - \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'asdsa\' in \'where clause\'', - 'code' => 1054, - )), - ), - 'SELECT id FROM table WHERE a=\'1970-01-01\' AND err-or id IN (\'1\')' => - array ( - 'error' => - \staabm\PHPStanDba\Error::__set_state(array( - 'message' => '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 \'table WHERE a=\'1970-01-01\' AND err-or id IN (\'1\') LIMIT 0\' at line 1 - -Simulated query: SELECT id FROM table WHERE a=\'1970-01-01\' AND err-or id IN (\'1\') LIMIT 0', - 'code' => 1064, - )), - ), - 'SELECT id FROM table WHERE err-or id IN (\'1\')' => - array ( - 'error' => - \staabm\PHPStanDba\Error::__set_state(array( - 'message' => '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 \'table WHERE err-or id IN (\'1\') LIMIT 0\' at line 1 - -Simulated query: SELECT id FROM table WHERE err-or id IN (\'1\') LIMIT 0', - 'code' => 1064, - )), - ), - 'SELECT id FROM table WHERE id IN (\'1\')' => - array ( - 'error' => - \staabm\PHPStanDba\Error::__set_state(array( - 'message' => '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 \'table WHERE id IN (\'1\') LIMIT 0\' at line 1 - -Simulated query: SELECT id FROM table WHERE id IN (\'1\') LIMIT 0', - 'code' => 1064, - )), - ), - 'Select * from ada - where adakzid = 15' => - array ( - 'error' => - \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'adakzid\' in \'where clause\'', - 'code' => 1054, - )), - ), ), 'runtimeConfig' => array ( diff --git a/composer.json b/composer.json index f9fab56f4..d28c8566d 100644 --- a/composer.json +++ b/composer.json @@ -7,8 +7,9 @@ "php": "^7.4 || ^8.0", "composer-runtime-api": "^2.0", "composer/semver": "^3.2", - "doctrine/dbal": "3.*|4.*", - "phpstan/phpstan": "^2.0" + "doctrine/dbal": "3.*", + "phpstan/phpstan": "^2.0", + "sqlftw/sqlftw": "^0.1.17" }, "require-dev": { "ext-mysqli": "*", diff --git a/src/Rules/QueryPlanAnalyzerRule.php b/src/Rules/QueryPlanAnalyzerRule.php index 4a1b46d3d..43b6eba3b 100644 --- a/src/Rules/QueryPlanAnalyzerRule.php +++ b/src/Rules/QueryPlanAnalyzerRule.php @@ -8,6 +8,9 @@ use PhpParser\Node\Expr\CallLike; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\New_; +use PhpParser\Node\Expr\StaticCall; +use PhpParser\Node\Identifier; +use PhpParser\Node\Name; use PhpParser\Node\Name\FullyQualified; use PHPStan\Analyser\Scope; use PHPStan\Reflection\ReflectionProvider; @@ -30,7 +33,7 @@ final class QueryPlanAnalyzerRule implements Rule /** * @var list */ - private array $classMethods; + public array $classMethods; private ReflectionProvider $reflectionProvider; @@ -56,6 +59,15 @@ public function processNode(Node $callLike, Scope $scope): array } $methodReflection = $scope->getMethodReflection($scope->getType($callLike->var), $callLike->name->toString()); + } elseif ($callLike instanceof StaticCall) { + if (! $callLike->name instanceof Identifier) { + return []; + } + if (! $callLike->class instanceof Name) { + return []; + } + $classType = $scope->resolveTypeByName($callLike->class); + $methodReflection = $scope->getMethodReflection($classType, $callLike->name->toString()); } elseif ($callLike instanceof New_) { if (! $callLike->class instanceof FullyQualified) { return []; @@ -105,7 +117,7 @@ public function processNode(Node $callLike, Scope $scope): array } /** - * @param MethodCall|New_ $callLike + * @param MethodCall|StaticCall|New_ $callLike * * @return list */ diff --git a/src/Rules/SyntaxErrorInPreparedStatementMethodRule.php b/src/Rules/SyntaxErrorInPreparedStatementMethodRule.php index 432d1e839..68774e6ed 100644 --- a/src/Rules/SyntaxErrorInPreparedStatementMethodRule.php +++ b/src/Rules/SyntaxErrorInPreparedStatementMethodRule.php @@ -8,6 +8,9 @@ use PhpParser\Node\Expr\CallLike; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\New_; +use PhpParser\Node\Expr\StaticCall; +use PhpParser\Node\Identifier; +use PhpParser\Node\Name; use PhpParser\Node\Name\FullyQualified; use PHPStan\Analyser\Scope; use PHPStan\Reflection\ReflectionProvider; @@ -57,6 +60,15 @@ public function processNode(Node $callLike, Scope $scope): array } $methodReflection = $scope->getMethodReflection($scope->getType($callLike->var), $callLike->name->toString()); + } elseif ($callLike instanceof StaticCall) { + if (! $callLike->name instanceof Identifier) { + return []; + } + if (! $callLike->class instanceof Name) { + return []; + } + $classType = $scope->resolveTypeByName($callLike->class); + $methodReflection = $scope->getMethodReflection($classType, $callLike->name->toString()); } elseif ($callLike instanceof New_) { if (! $callLike->class instanceof FullyQualified) { return []; @@ -96,7 +108,7 @@ public function processNode(Node $callLike, Scope $scope): array } /** - * @param MethodCall|New_ $callLike + * @param MethodCall|StaticCall|New_ $callLike * * @return list */ diff --git a/src/Rules/SyntaxErrorInQueryMethodRule.php b/src/Rules/SyntaxErrorInQueryMethodRule.php index 651375798..457515f42 100644 --- a/src/Rules/SyntaxErrorInQueryMethodRule.php +++ b/src/Rules/SyntaxErrorInQueryMethodRule.php @@ -5,7 +5,11 @@ namespace staabm\PHPStanDba\Rules; use PhpParser\Node; +use PhpParser\Node\Expr\CallLike; use PhpParser\Node\Expr\MethodCall; +use PhpParser\Node\Expr\StaticCall; +use PhpParser\Node\Identifier; +use PhpParser\Node\Name; use PHPStan\Analyser\Scope; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\Rule; @@ -15,7 +19,7 @@ use staabm\PHPStanDba\UnresolvableQueryException; /** - * @implements Rule + * @implements Rule * * @see SyntaxErrorInQueryMethodRuleTest */ @@ -39,16 +43,29 @@ public function __construct(array $classMethods, ReflectionProvider $reflectionP public function getNodeType(): string { - return MethodCall::class; + return CallLike::class; } - public function processNode(Node $node, Scope $scope): array + public function processNode(Node $callLike, Scope $scope): array { - if (! $node->name instanceof Node\Identifier) { + if ($callLike instanceof MethodCall) { + if (! $callLike->name instanceof Identifier) { + return []; + } + $methodReflection = $scope->getMethodReflection($scope->getType($callLike->var), $callLike->name->toString()); + } elseif ($callLike instanceof StaticCall) { + if (! $callLike->name instanceof Identifier) { + return []; + } + if (! $callLike->class instanceof Name) { + return []; + } + $classType = $scope->resolveTypeByName($callLike->class); + $methodReflection = $scope->getMethodReflection($classType, $callLike->name->toString()); + } else { return []; } - $methodReflection = $scope->getMethodReflection($scope->getType($node->var), $node->name->toString()); if (null === $methodReflection) { return []; } @@ -79,7 +96,7 @@ public function processNode(Node $node, Scope $scope): array return []; } - $args = $node->getArgs(); + $args = $callLike->getArgs(); if (! \array_key_exists($queryArgPosition, $args)) { return []; @@ -98,13 +115,13 @@ public function processNode(Node $node, Scope $scope): array $queryError = $queryReflection->validateQueryString($queryString); if (null !== $queryError) { return [ - RuleErrorBuilder::message($queryError->asRuleMessage())->identifier('dba.syntaxError')->line($node->getStartLine())->build(), + RuleErrorBuilder::message($queryError->asRuleMessage())->identifier('dba.syntaxError')->line($callLike->getStartLine())->build(), ]; } } } catch (UnresolvableQueryException $exception) { return [ - RuleErrorBuilder::message($exception->asRuleMessage())->tip($exception::getTip())->identifier('dba.unresolvableQuery')->line($node->getStartLine())->build(), + RuleErrorBuilder::message($exception->asRuleMessage())->tip($exception::getTip())->identifier('dba.unresolvableQuery')->line($callLike->getStartLine())->build(), ]; } diff --git a/tests/default/Fixture/StaticDatabase.php b/tests/default/Fixture/StaticDatabase.php new file mode 100644 index 000000000..d87d3328b --- /dev/null +++ b/tests/default/Fixture/StaticDatabase.php @@ -0,0 +1,28 @@ + array ( 'type-description' => 'array{email: string, 0: string}', ), - 3 => - array ( - 'type-description' => 'array{email: string}', - ), ), ), 'SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada' => @@ -322,10 +318,6 @@ FROM ada' => array ( 'type-description' => 'array{email: string, 0: string, adaid: int<-32768, 32767>, 1: int<-32768, 32767>}', ), - 3 => - array ( - 'type-description' => 'array{email: string, adaid: int<-32768, 32767>}', - ), ), ), 'SELECT email, adaid FROM ada LIMIT 1' => diff --git a/tests/rules/QueryPlanAnalyzerRuleTest.php b/tests/rules/QueryPlanAnalyzerRuleTest.php index 210e43f70..09f9954fc 100644 --- a/tests/rules/QueryPlanAnalyzerRuleTest.php +++ b/tests/rules/QueryPlanAnalyzerRuleTest.php @@ -42,7 +42,10 @@ protected function getRule(): Rule QueryReflection::getRuntimeConfiguration()->debugMode($this->debugMode); QueryReflection::getRuntimeConfiguration()->analyzeQueryPlans($this->numberOfAllowedUnindexedReads, $this->numberOfRowsNotRequiringIndex); - return self::getContainer()->getByType(QueryPlanAnalyzerRule::class); + $rule = self::getContainer()->getByType(QueryPlanAnalyzerRule::class); + $rule->classMethods[] = 'staabm\PHPStanDba\Tests\Fixture\StaticDatabase::query#0'; + $rule->classMethods[] = 'staabm\PHPStanDba\Tests\Fixture\StaticDatabase::executeQuery#0'; + return $rule; } public static function getAdditionalConfigFiles(): array @@ -54,14 +57,6 @@ public static function getAdditionalConfigFiles(): array public function testNotUsingIndex(): void { - if ('pdo-pgsql' === getenv('DBA_REFLECTOR')) { - self::markTestSkipped('query plan analyzer is not yet implemented for pgsql'); - } - - if (ReflectorFactory::MODE_RECORDING !== getenv('DBA_MODE')) { - self::markTestSkipped('query plan analyzer requires a active database connection'); - } - $this->numberOfAllowedUnindexedReads = true; $this->numberOfRowsNotRequiringIndex = 2; @@ -94,19 +89,21 @@ public function testNotUsingIndex(): void 28, $tip, ], + [ + "Query is not using an index on table 'ada'." . $proposal, + 78, + $tip, + ], + [ + "Query is not using an index on table 'ada'." . $proposal, + 79, + $tip, + ], ]); } public function testNotUsingIndexInDebugMode(): void { - if ('pdo-pgsql' === getenv('DBA_REFLECTOR')) { - self::markTestSkipped('query plan analyzer is not yet implemented for pgsql'); - } - - if (ReflectorFactory::MODE_RECORDING !== getenv('DBA_MODE')) { - self::markTestSkipped('query plan analyzer requires a active database connection'); - } - $this->debugMode = true; $this->numberOfAllowedUnindexedReads = true; $this->numberOfRowsNotRequiringIndex = 2; @@ -160,6 +157,16 @@ public function testNotUsingIndexInDebugMode(): void 73, UnresolvableQueryStringTypeException::getTip(), ], + [ + "Query is not using an index on table 'ada'." . $proposal, + 78, + $tip, + ], + [ + "Query is not using an index on table 'ada'." . $proposal, + 79, + $tip, + ], ]); } } diff --git a/tests/rules/SyntaxErrorInPreparedStatementMethodRuleTest.php b/tests/rules/SyntaxErrorInPreparedStatementMethodRuleTest.php index c5483e732..bebc371a8 100644 --- a/tests/rules/SyntaxErrorInPreparedStatementMethodRuleTest.php +++ b/tests/rules/SyntaxErrorInPreparedStatementMethodRuleTest.php @@ -21,6 +21,8 @@ protected function getRule(): Rule $rule = self::getContainer()->getByType(SyntaxErrorInPreparedStatementMethodRule::class); $rule->classMethods[] = 'staabm\PHPStanDba\Tests\Fixture\Connection::preparedQuery'; $rule->classMethods[] = 'staabm\PHPStanDba\Tests\Fixture\PreparedStatement::__construct'; + $rule->classMethods[] = 'staabm\PHPStanDba\Tests\Fixture\StaticDatabase::preparedQuery'; + $rule->classMethods[] = 'staabm\PHPStanDba\Tests\Fixture\StaticDatabase::prepare'; return $rule; } @@ -92,6 +94,14 @@ public function testSyntaxErrorInQueryRule(): void 'Query expects placeholder :freigabe1u1, but it is missing from values given.', 325, ], + [ + "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 'freigabe1u1 FROM ada LIMIT 0' at line 1 (1064).", + 388, + ], + [ + "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 'freigabe1u1 FROM ada LIMIT 0' at line 1 (1064).", + 389, + ], ]; } elseif (PdoPgSqlQueryReflector::NAME === getenv('DBA_REFLECTOR')) { $expectedErrors = [ @@ -171,6 +181,18 @@ public function testSyntaxErrorInQueryRule(): void 'Query expects placeholder :freigabe1u1, but it is missing from values given.', 325, ], + [ + 'Query error: SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "freigabe1u1" +LINE 1: SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada LIMIT... + ^ (42601).', + 388, + ], + [ + 'Query error: SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "freigabe1u1" +LINE 1: SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada LIMIT... + ^ (42601).', + 389, + ], ]; } elseif (PdoMysqlQueryReflector::NAME === getenv('DBA_REFLECTOR')) { if ('mariadb' === $_ENV['DBA_PLATFORM']) { @@ -230,6 +252,14 @@ public function testSyntaxErrorInQueryRule(): void 'Query expects placeholder :freigabe1u1, but it is missing from values given.', 325, ], + [ + "Query error: SQLSTATE[42000]: Syntax error or access violation: 1064 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 'freigabe1u1 FROM ada LIMIT 0' at line 1 (42000).", + 388, + ], + [ + "Query error: SQLSTATE[42000]: Syntax error or access violation: 1064 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 'freigabe1u1 FROM ada LIMIT 0' at line 1 (42000).", + 389, + ], ]; } else { throw new \RuntimeException('Unsupported DBA_REFLECTOR ' . getenv('DBA_REFLECTOR')); diff --git a/tests/rules/SyntaxErrorInQueryMethodRuleTest.php b/tests/rules/SyntaxErrorInQueryMethodRuleTest.php index d2a4eb1dc..f6ab9eef4 100644 --- a/tests/rules/SyntaxErrorInQueryMethodRuleTest.php +++ b/tests/rules/SyntaxErrorInQueryMethodRuleTest.php @@ -20,7 +20,10 @@ class SyntaxErrorInQueryMethodRuleTest extends RuleTestCase { protected function getRule(): Rule { - return self::getContainer()->getByType(SyntaxErrorInQueryMethodRule::class); + $rule = self::getContainer()->getByType(SyntaxErrorInQueryMethodRule::class); + $rule->classMethods[] = 'staabm\PHPStanDba\Tests\Fixture\StaticDatabase::query#0'; + $rule->classMethods[] = 'staabm\PHPStanDba\Tests\Fixture\StaticDatabase::prepare#0'; + return $rule; } public static function getAdditionalConfigFiles(): array @@ -114,6 +117,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 'freigabe1u1 FROM ada LIMIT 0' 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 'freigabe1u1 FROM ada LIMIT 0' at line 1 (1064).", + 156, + ], ]; } elseif (PdoMysqlQueryReflector::NAME === getenv('DBA_REFLECTOR')) { if ('mariadb' === $_ENV['DBA_PLATFORM']) { @@ -185,6 +196,14 @@ public function testSyntaxErrorInQueryRule(): void "Query error: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'phpstan_dba.adasfd' doesn't exist (42S02).", 138, ], + [ + "Query error: SQLSTATE[42000]: Syntax error or access violation: 1064 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 'freigabe1u1 FROM ada LIMIT 0' at line 1 (42000).", + 155, + ], + [ + "Query error: SQLSTATE[42000]: Syntax error or access violation: 1064 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 'freigabe1u1 FROM ada LIMIT 0' at line 1 (42000).", + 156, + ], ]; } elseif (PdoPgSqlQueryReflector::NAME === getenv('DBA_REFLECTOR')) { $expected = [ @@ -296,6 +315,18 @@ public function testSyntaxErrorInQueryRule(): void ^ (42601).', 138, ], + [ + 'Query error: SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "freigabe1u1" +LINE 1: SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada LIMIT... + ^ (42601).', + 155, + ], + [ + 'Query error: SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "freigabe1u1" +LINE 1: SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada LIMIT... + ^ (42601).', + 156, + ], ]; } else { throw new \RuntimeException('Unsupported DBA_REFLECTOR ' . getenv('DBA_REFLECTOR')); diff --git a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache index d6ab8e947..4319ea1e1 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache @@ -55,6 +55,14 @@ Simulated query: EXPLAIN REPLACE INTO `ada` SET email="test" WHERE adaid = 1', 'code' => 1146, )), ), + 'EXPLAIN UPDATE package SET indexedAt=\'1970-01-01\' WHERE id IN (\'1\') AND (indexedAt IS NULL OR indexedAt <= crawledAt)' => + array ( + 'error' => + \staabm\PHPStanDba\Error::__set_state(array( + 'message' => 'Table \'phpstan_dba.package\' doesn\'t exist', + 'code' => 1146, + )), + ), 'EXPLAIN UPDATE package SET indexedAt=\'1970-01-01\' WHERE id IN (NULL) AND (indexedAt IS NULL OR indexedAt <= crawledAt)' => array ( 'error' => @@ -125,7 +133,7 @@ Simulated query: SELECT * FROM 1 LIMIT 0', array ( 'error' => \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'doesNotExist\' in \'group statement\'', + 'message' => 'Unknown column \'doesNotExist\' in \'GROUP BY\'', 'code' => 1054, )), ), @@ -133,7 +141,7 @@ Simulated query: SELECT * FROM 1 LIMIT 0', array ( 'error' => \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', + 'message' => 'Unknown column \'doesNotExist\' in \'ORDER BY\'', 'code' => 1054, )), ), @@ -151,7 +159,7 @@ Simulated query: SELECT * FROM 1 LIMIT 0', array ( 'error' => \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', + 'message' => 'Unknown column \'doesNotExist\' in \'WHERE\'', 'code' => 1054, )), ), @@ -257,7 +265,7 @@ Simulated query: SELECT FROM WHERE LIMIT 0', array ( 'error' => \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'doesNotExist\' in \'field list\'', + 'message' => 'Unknown column \'doesNotExist\' in \'SELECT\'', 'code' => 1054, )), ), @@ -354,7 +362,7 @@ Simulated query: SELECT FROM WHERE LIMIT 0', array ( 'error' => \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'xy\' in \'group statement\'', + 'message' => 'Unknown column \'xy\' in \'GROUP BY\'', 'code' => 1054, )), ), @@ -416,6 +424,14 @@ Simulated query: SELECT FROM WHERE LIMIT 0', 'code' => 1064, )), ), + 'SELECT email, adaid GROUP BY xy FROM ada LIMIT 1' => + array ( + 'error' => + \staabm\PHPStanDba\Error::__set_state(array( + 'message' => '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 \'FROM ada LIMIT 0\' at line 1', + 'code' => 1064, + )), + ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada' => array ( 'result' => @@ -464,7 +480,7 @@ Simulated query: SELECT FROM WHERE LIMIT 0', array ( 'error' => \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'asdsa\' in \'where clause\'', + 'message' => 'Unknown column \'asdsa\' in \'WHERE\'', 'code' => 1054, )), ), @@ -472,7 +488,7 @@ Simulated query: SELECT FROM WHERE LIMIT 0', array ( 'error' => \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'asdsa\' in \'where clause\'', + 'message' => 'Unknown column \'asdsa\' in \'WHERE\'', 'code' => 1054, )), ), @@ -490,7 +506,7 @@ Simulated query: SELECT FROM WHERE LIMIT 0', array ( 'error' => \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'does_not_exist\' in \'field list\'', + 'message' => 'Unknown column \'does_not_exist\' in \'SELECT\'', 'code' => 1054, )), ), @@ -498,7 +514,7 @@ Simulated query: SELECT FROM WHERE LIMIT 0', array ( 'error' => \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'does_not_exist\' in \'field list\'', + 'message' => 'Unknown column \'does_not_exist\' in \'SELECT\'', 'code' => 1054, )), ), diff --git a/tests/rules/data/query-plan-analyzer.php b/tests/rules/data/query-plan-analyzer.php index ba4e69e64..aa77e8387 100644 --- a/tests/rules/data/query-plan-analyzer.php +++ b/tests/rules/data/query-plan-analyzer.php @@ -72,4 +72,10 @@ public function bug442(Connection $conn, string $table) $query = "SELECT email, adaid FROM `$table` WHERE adaid = ?"; $conn->fetchAssociative($query, [1]); } + + public function staticCallTests(): void + { + staabm\PHPStanDba\Tests\Fixture\StaticDatabase::query("SELECT * FROM `ada` WHERE email = 'test@example.com';"); + staabm\PHPStanDba\Tests\Fixture\StaticDatabase::executeQuery("SELECT *,adaid FROM `ada` WHERE email = 'test@example.com';"); + } } diff --git a/tests/rules/data/syntax-error-in-prepared-statement.php b/tests/rules/data/syntax-error-in-prepared-statement.php index 537d22f72..d5c244265 100644 --- a/tests/rules/data/syntax-error-in-prepared-statement.php +++ b/tests/rules/data/syntax-error-in-prepared-statement.php @@ -382,4 +382,10 @@ protected function conditionalUnnamedPlaceholder(Connection $connection, array $ $connection->preparedQuery($query, $values); } + + public function staticCallPreparedStatementTests(): void + { + staabm\PHPStanDba\Tests\Fixture\StaticDatabase::preparedQuery('SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada', []); + staabm\PHPStanDba\Tests\Fixture\StaticDatabase::prepare('SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE asdsa=?', [1]); + } } diff --git a/tests/rules/data/syntax-error-in-query-method.php b/tests/rules/data/syntax-error-in-query-method.php index 74f93c4f2..a2f76bc4d 100644 --- a/tests/rules/data/syntax-error-in-query-method.php +++ b/tests/rules/data/syntax-error-in-query-method.php @@ -149,4 +149,9 @@ public function bug458(PDO $pdo) $pdo->query('SELECT * FROM ' . $table . ' LIMIT 1'); } + public function staticCallQueryTests(): void + { + staabm\PHPStanDba\Tests\Fixture\StaticDatabase::query('SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada', PDO::FETCH_ASSOC); + staabm\PHPStanDba\Tests\Fixture\StaticDatabase::prepare('SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada'); + } } diff --git a/tests/sqlAst/config/.phpunit-phpstan-dba-mysqli.cache b/tests/sqlAst/config/.phpunit-phpstan-dba-mysqli.cache index 2541ea5e9..f8bd47ad5 100644 --- a/tests/sqlAst/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/sqlAst/config/.phpunit-phpstan-dba-mysqli.cache @@ -74,7 +74,7 @@ array ( 5 => array ( - 'type-description' => 'array{3: int, 0: int}', + 'type-description' => 'array{3: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', ), ), ), @@ -84,7 +84,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int, 0: int}', + 'type-description' => 'array{col: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', ), ), ), @@ -114,7 +114,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int, 0: int}', + 'type-description' => 'array{col: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', ), ), ), @@ -134,7 +134,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', + 'type-description' => 'array{col: int<-2147483648, 2147483647>|null, 0: int<-2147483648, 2147483647>|null}', ), ), ), @@ -144,7 +144,7 @@ array ( 5 => array ( - 'type-description' => 'array{field: int, 0: int}', + 'type-description' => 'array{field: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', ), ), ), @@ -224,7 +224,7 @@ array ( 5 => array ( - 'type-description' => 'array{abs: int, 0: int}', + 'type-description' => 'array{abs: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', ), ), ), @@ -724,7 +724,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int|null, 0: int|null}', + 'type-description' => 'array{col: int<-2147483648, 2147483647>|null, 0: int<-2147483648, 2147483647>|null}', ), ), ), @@ -734,7 +734,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int|null, 0: int|null}', + 'type-description' => 'array{col: int<-2147483648, 2147483647>|null, 0: int<-2147483648, 2147483647>|null}', ), ), ), @@ -974,7 +974,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int, 0: int}', + 'type-description' => 'array{col: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', ), ), ), @@ -1044,7 +1044,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: string|null, 0: string|null}', + 'type-description' => 'array{col: mixed, 0: mixed}', ), ), ), @@ -1054,7 +1054,7 @@ array ( 5 => array ( - 'type-description' => 'array{field: int, 0: int}', + 'type-description' => 'array{field: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', ), ), ), @@ -1064,7 +1064,7 @@ array ( 5 => array ( - 'type-description' => 'array{field: int, 0: int}', + 'type-description' => 'array{field: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', ), ), ), @@ -1074,7 +1074,7 @@ array ( 5 => array ( - 'type-description' => 'array{field: int|null, 0: int|null}', + 'type-description' => 'array{field: int<-2147483648, 2147483647>|null, 0: int<-2147483648, 2147483647>|null}', ), ), ), @@ -1084,7 +1084,7 @@ array ( 5 => array ( - 'type-description' => 'array{n1: int, 0: int}', + 'type-description' => 'array{n1: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', ), ), ), @@ -1094,7 +1094,7 @@ array ( 5 => array ( - 'type-description' => 'array{n1: int, 0: int}', + 'type-description' => 'array{n1: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', ), ), ), @@ -1114,7 +1114,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int, 0: int}', + 'type-description' => 'array{col: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', ), ), ), @@ -1124,7 +1124,7 @@ array ( 5 => array ( - 'type-description' => 'array{field: int|null, 0: int|null}', + 'type-description' => 'array{field: int<-2147483648, 2147483647>|null, 0: int<-2147483648, 2147483647>|null}', ), ), ), @@ -1134,7 +1134,7 @@ array ( 5 => array ( - 'type-description' => 'array{field: int, 0: int}', + 'type-description' => 'array{field: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', ), ), ), @@ -1144,7 +1144,7 @@ array ( 5 => array ( - 'type-description' => 'array{field: int|null, 0: int|null}', + 'type-description' => 'array{field: int<-2147483648, 2147483647>|null, 0: int<-2147483648, 2147483647>|null}', ), ), ), @@ -1284,7 +1284,7 @@ array ( 5 => array ( - 'type-description' => 'array{max: mixed, 0: mixed}', + 'type-description' => 'array{max: string|null, 0: string|null}', ), ), ), @@ -1354,7 +1354,7 @@ array ( 5 => array ( - 'type-description' => 'array{min: mixed, 0: mixed}', + 'type-description' => 'array{min: string|null, 0: string|null}', ), ), ), @@ -1364,7 +1364,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int|null, 0: int|null}', + 'type-description' => 'array{col: int<-2147483648, 2147483647>|null, 0: int<-2147483648, 2147483647>|null}', ), ), ), @@ -1374,7 +1374,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int|null, 0: int|null}', + 'type-description' => 'array{col: int<-2147483648, 2147483647>|null, 0: int<-2147483648, 2147483647>|null}', ), ), ), @@ -1444,7 +1444,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int|null, 0: int|null}', + 'type-description' => 'array{col: int<-2147483648, 2147483647>|null, 0: int<-2147483648, 2147483647>|null}', ), ), ), @@ -1464,7 +1464,7 @@ array ( 5 => array ( - 'type-description' => 'array{abs: int, 0: int}', + 'type-description' => 'array{abs: int<-32768, 32767>, 0: int<-32768, 32767>}', ), ), ), From 7519e43560bca95b5462f632c4cc68c23817ff48 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 7 Aug 2025 11:04:54 +0200 Subject: [PATCH 2/9] Discard changes to composer.json --- composer.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index d28c8566d..f9fab56f4 100644 --- a/composer.json +++ b/composer.json @@ -7,9 +7,8 @@ "php": "^7.4 || ^8.0", "composer-runtime-api": "^2.0", "composer/semver": "^3.2", - "doctrine/dbal": "3.*", - "phpstan/phpstan": "^2.0", - "sqlftw/sqlftw": "^0.1.17" + "doctrine/dbal": "3.*|4.*", + "phpstan/phpstan": "^2.0" }, "require-dev": { "ext-mysqli": "*", From e4516986ded2271c98f1511207d0afce5f748c21 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 7 Aug 2025 11:06:29 +0200 Subject: [PATCH 3/9] fix --- tests/rules/data/query-plan-analyzer.php | 4 ++-- tests/rules/data/syntax-error-in-prepared-statement.php | 4 ++-- tests/rules/data/syntax-error-in-query-method.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/rules/data/query-plan-analyzer.php b/tests/rules/data/query-plan-analyzer.php index aa77e8387..5ac10508c 100644 --- a/tests/rules/data/query-plan-analyzer.php +++ b/tests/rules/data/query-plan-analyzer.php @@ -75,7 +75,7 @@ public function bug442(Connection $conn, string $table) public function staticCallTests(): void { - staabm\PHPStanDba\Tests\Fixture\StaticDatabase::query("SELECT * FROM `ada` WHERE email = 'test@example.com';"); - staabm\PHPStanDba\Tests\Fixture\StaticDatabase::executeQuery("SELECT *,adaid FROM `ada` WHERE email = 'test@example.com';"); + \staabm\PHPStanDba\Tests\Fixture\StaticDatabase::query("SELECT * FROM `ada` WHERE email = 'test@example.com';"); + \staabm\PHPStanDba\Tests\Fixture\StaticDatabase::executeQuery("SELECT *,adaid FROM `ada` WHERE email = 'test@example.com';"); } } diff --git a/tests/rules/data/syntax-error-in-prepared-statement.php b/tests/rules/data/syntax-error-in-prepared-statement.php index d5c244265..63b2a2fd9 100644 --- a/tests/rules/data/syntax-error-in-prepared-statement.php +++ b/tests/rules/data/syntax-error-in-prepared-statement.php @@ -385,7 +385,7 @@ protected function conditionalUnnamedPlaceholder(Connection $connection, array $ public function staticCallPreparedStatementTests(): void { - staabm\PHPStanDba\Tests\Fixture\StaticDatabase::preparedQuery('SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada', []); - staabm\PHPStanDba\Tests\Fixture\StaticDatabase::prepare('SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE asdsa=?', [1]); + \staabm\PHPStanDba\Tests\Fixture\StaticDatabase::preparedQuery('SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada', []); + \staabm\PHPStanDba\Tests\Fixture\StaticDatabase::prepare('SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE asdsa=?', [1]); } } diff --git a/tests/rules/data/syntax-error-in-query-method.php b/tests/rules/data/syntax-error-in-query-method.php index a2f76bc4d..ac996e123 100644 --- a/tests/rules/data/syntax-error-in-query-method.php +++ b/tests/rules/data/syntax-error-in-query-method.php @@ -151,7 +151,7 @@ public function bug458(PDO $pdo) public function staticCallQueryTests(): void { - staabm\PHPStanDba\Tests\Fixture\StaticDatabase::query('SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada', PDO::FETCH_ASSOC); - staabm\PHPStanDba\Tests\Fixture\StaticDatabase::prepare('SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada'); + \staabm\PHPStanDba\Tests\Fixture\StaticDatabase::query('SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada', PDO::FETCH_ASSOC); + \staabm\PHPStanDba\Tests\Fixture\StaticDatabase::prepare('SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada'); } } From 50bb11da01811e59d0bb2d65738a4efb87d00678 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 7 Aug 2025 11:12:23 +0200 Subject: [PATCH 4/9] partly revert --- tests/rules/QueryPlanAnalyzerRuleTest.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/rules/QueryPlanAnalyzerRuleTest.php b/tests/rules/QueryPlanAnalyzerRuleTest.php index 09f9954fc..cafc4be3b 100644 --- a/tests/rules/QueryPlanAnalyzerRuleTest.php +++ b/tests/rules/QueryPlanAnalyzerRuleTest.php @@ -57,6 +57,14 @@ public static function getAdditionalConfigFiles(): array public function testNotUsingIndex(): void { + if ('pdo-pgsql' === getenv('DBA_REFLECTOR')) { + self::markTestSkipped('query plan analyzer is not yet implemented for pgsql'); + } + + if (ReflectorFactory::MODE_RECORDING !== getenv('DBA_MODE')) { + self::markTestSkipped('query plan analyzer requires a active database connection'); + } + $this->numberOfAllowedUnindexedReads = true; $this->numberOfRowsNotRequiringIndex = 2; @@ -104,6 +112,14 @@ public function testNotUsingIndex(): void public function testNotUsingIndexInDebugMode(): void { + if ('pdo-pgsql' === getenv('DBA_REFLECTOR')) { + self::markTestSkipped('query plan analyzer is not yet implemented for pgsql'); + } + + if (ReflectorFactory::MODE_RECORDING !== getenv('DBA_MODE')) { + self::markTestSkipped('query plan analyzer requires a active database connection'); + } + $this->debugMode = true; $this->numberOfAllowedUnindexedReads = true; $this->numberOfRowsNotRequiringIndex = 2; From 3bb6011e1b71623d890491d8423edd0ddfe027e3 Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Thu, 7 Aug 2025 12:15:48 +0300 Subject: [PATCH 5/9] fix --- tests/rules/QueryPlanAnalyzerRuleTest.php | 16 ++++++++++++++++ tests/rules/SyntaxErrorInQueryMethodRuleTest.php | 12 ++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/tests/rules/QueryPlanAnalyzerRuleTest.php b/tests/rules/QueryPlanAnalyzerRuleTest.php index 09f9954fc..cafc4be3b 100644 --- a/tests/rules/QueryPlanAnalyzerRuleTest.php +++ b/tests/rules/QueryPlanAnalyzerRuleTest.php @@ -57,6 +57,14 @@ public static function getAdditionalConfigFiles(): array public function testNotUsingIndex(): void { + if ('pdo-pgsql' === getenv('DBA_REFLECTOR')) { + self::markTestSkipped('query plan analyzer is not yet implemented for pgsql'); + } + + if (ReflectorFactory::MODE_RECORDING !== getenv('DBA_MODE')) { + self::markTestSkipped('query plan analyzer requires a active database connection'); + } + $this->numberOfAllowedUnindexedReads = true; $this->numberOfRowsNotRequiringIndex = 2; @@ -104,6 +112,14 @@ public function testNotUsingIndex(): void public function testNotUsingIndexInDebugMode(): void { + if ('pdo-pgsql' === getenv('DBA_REFLECTOR')) { + self::markTestSkipped('query plan analyzer is not yet implemented for pgsql'); + } + + if (ReflectorFactory::MODE_RECORDING !== getenv('DBA_MODE')) { + self::markTestSkipped('query plan analyzer requires a active database connection'); + } + $this->debugMode = true; $this->numberOfAllowedUnindexedReads = true; $this->numberOfRowsNotRequiringIndex = 2; diff --git a/tests/rules/SyntaxErrorInQueryMethodRuleTest.php b/tests/rules/SyntaxErrorInQueryMethodRuleTest.php index f6ab9eef4..a401bb4de 100644 --- a/tests/rules/SyntaxErrorInQueryMethodRuleTest.php +++ b/tests/rules/SyntaxErrorInQueryMethodRuleTest.php @@ -119,11 +119,11 @@ public function testSyntaxErrorInQueryRule(): void ], [ "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 'freigabe1u1 FROM ada LIMIT 0' at line 1 (1064).", - 155, + 154, ], [ "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 'freigabe1u1 FROM ada LIMIT 0' at line 1 (1064).", - 156, + 155, ], ]; } elseif (PdoMysqlQueryReflector::NAME === getenv('DBA_REFLECTOR')) { @@ -198,11 +198,11 @@ public function testSyntaxErrorInQueryRule(): void ], [ "Query error: SQLSTATE[42000]: Syntax error or access violation: 1064 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 'freigabe1u1 FROM ada LIMIT 0' at line 1 (42000).", - 155, + 154, ], [ "Query error: SQLSTATE[42000]: Syntax error or access violation: 1064 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 'freigabe1u1 FROM ada LIMIT 0' at line 1 (42000).", - 156, + 155, ], ]; } elseif (PdoPgSqlQueryReflector::NAME === getenv('DBA_REFLECTOR')) { @@ -319,13 +319,13 @@ public function testSyntaxErrorInQueryRule(): void 'Query error: SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "freigabe1u1" LINE 1: SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada LIMIT... ^ (42601).', - 155, + 154, ], [ 'Query error: SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "freigabe1u1" LINE 1: SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada LIMIT... ^ (42601).', - 156, + 155, ], ]; } else { From 7648e010924a39b53d92adf974b8a4019f0f7919 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 7 Aug 2025 11:17:49 +0200 Subject: [PATCH 6/9] fix expectations --- .phpstan-dba-mysqli.cache | 10 ++-- .phpstan-dba-pdo-mysql.cache | 33 +----------- .../.phpunit-phpstan-dba-pdo-mysql.cache | 8 --- ...ErrorInPreparedStatementMethodRuleTest.php | 8 ++- .../SyntaxErrorInQueryMethodRuleTest.php | 12 ++--- .../config/.phpunit-phpstan-dba-mysqli.cache | 18 +++---- .../config/.phpunit-phpstan-dba-mysqli.cache | 50 +++++++++---------- 7 files changed, 51 insertions(+), 88 deletions(-) diff --git a/.phpstan-dba-mysqli.cache b/.phpstan-dba-mysqli.cache index e295303a4..888331abd 100644 --- a/.phpstan-dba-mysqli.cache +++ b/.phpstan-dba-mysqli.cache @@ -1,6 +1,6 @@ 'v12-new-cache5', - 'schemaHash' => 'cc7b87e840d13ff393d87083b544963d', + 'schemaHash' => '72813316a311d2e2b9384c458247d011', 'records' => array ( 'SELECT @@ -46,7 +46,11 @@ array ( 5 => array ( - 'type-description' => 'array{dbsignature: string|null, 0: string|null, grouper: int<-2147483648, 2147483647>, 1: int<-2147483648, 2147483647>}', + 'type-description' => 'array{dbsignature: string|null, 0: string|null, grouper: int, 1: int}', + ), + 3 => + array ( + 'type-description' => 'array{dbsignature: string|null, grouper: int}', ), ), ), @@ -58,7 +62,7 @@ array ( 5 => array ( - 'type-description' => 'array{column_name: string, 0: string, column_default: string|null, 1: string|null, is_nullable: string, 2: string}', + 'type-description' => 'array{COLUMN_NAME: string|null, 0: string|null, COLUMN_DEFAULT: string|null, 1: string|null, IS_NULLABLE: string, 2: string}', ), ), ), diff --git a/.phpstan-dba-pdo-mysql.cache b/.phpstan-dba-pdo-mysql.cache index 7c82ddc1d..3e5688b32 100644 --- a/.phpstan-dba-pdo-mysql.cache +++ b/.phpstan-dba-pdo-mysql.cache @@ -1,23 +1,8 @@ 'v12-new-cache5', - 'schemaHash' => 'f94fe2b38e193ad685009d3f4942f476', + 'schemaHash' => '72813316a311d2e2b9384c458247d011', 'records' => array ( - 'SELECT - coalesce(COLUMN_NAME, \'\') as COLUMN_NAME, - coalesce(EXTRA, \'\') as EXTRA, - COLUMN_TYPE - FROM information_schema.columns - WHERE table_name = \'1970-01-01\' AND table_schema = DATABASE()' => - array ( - 'result' => - array ( - 5 => - array ( - 'type-description' => 'array{COLUMN_NAME: string, 0: string, EXTRA: string, 1: string, COLUMN_TYPE: string, 2: string}', - ), - ), - ), 'SELECT MD5( GROUP_CONCAT( @@ -48,22 +33,6 @@ array ( 'type-description' => 'array{dbsignature: string|null, 0: string|null, grouper: int, 1: int}', ), - 3 => - array ( - 'type-description' => 'array{dbsignature: string|null, grouper: int}', - ), - ), - ), - 'SELECT column_name, column_default, is_nullable - FROM information_schema.columns - WHERE table_name = \'1970-01-01\'' => - array ( - 'result' => - array ( - 5 => - array ( - 'type-description' => 'array{COLUMN_NAME: string|null, 0: string|null, COLUMN_DEFAULT: string|null, 1: string|null, IS_NULLABLE: string, 2: string}', - ), ), ), ), diff --git a/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache b/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache index 1c7b3a8d9..d4f38badf 100644 --- a/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache +++ b/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache @@ -300,10 +300,6 @@ FROM ada' => array ( 'type-description' => 'array{email: string, 0: string}', ), - 3 => - array ( - 'type-description' => 'array{email: string}', - ), ), ), 'SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada' => @@ -322,10 +318,6 @@ FROM ada' => array ( 'type-description' => 'array{email: string, 0: string, adaid: int<-32768, 32767>, 1: int<-32768, 32767>}', ), - 3 => - array ( - 'type-description' => 'array{email: string, adaid: int<-32768, 32767>}', - ), ), ), 'SELECT email, adaid FROM ada LIMIT 1' => diff --git a/tests/rules/SyntaxErrorInPreparedStatementMethodRuleTest.php b/tests/rules/SyntaxErrorInPreparedStatementMethodRuleTest.php index bebc371a8..ab33f41f5 100644 --- a/tests/rules/SyntaxErrorInPreparedStatementMethodRuleTest.php +++ b/tests/rules/SyntaxErrorInPreparedStatementMethodRuleTest.php @@ -99,7 +99,7 @@ public function testSyntaxErrorInQueryRule(): void 388, ], [ - "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 'freigabe1u1 FROM ada LIMIT 0' at line 1 (1064).", + "Query error: Unknown column 'asdsa' in 'where clause' (1054).", 389, ], ]; @@ -188,9 +188,7 @@ public function testSyntaxErrorInQueryRule(): void 388, ], [ - 'Query error: SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "freigabe1u1" -LINE 1: SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada LIMIT... - ^ (42601).', + "Query error: Unknown column 'asdsa' in 'where clause' (1054).", 389, ], ]; @@ -257,7 +255,7 @@ public function testSyntaxErrorInQueryRule(): void 388, ], [ - "Query error: SQLSTATE[42000]: Syntax error or access violation: 1064 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 'freigabe1u1 FROM ada LIMIT 0' at line 1 (42000).", + "Query error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'asdsa' in 'where clause' (42S22).", 389, ], ]; diff --git a/tests/rules/SyntaxErrorInQueryMethodRuleTest.php b/tests/rules/SyntaxErrorInQueryMethodRuleTest.php index f6ab9eef4..a401bb4de 100644 --- a/tests/rules/SyntaxErrorInQueryMethodRuleTest.php +++ b/tests/rules/SyntaxErrorInQueryMethodRuleTest.php @@ -119,11 +119,11 @@ public function testSyntaxErrorInQueryRule(): void ], [ "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 'freigabe1u1 FROM ada LIMIT 0' at line 1 (1064).", - 155, + 154, ], [ "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 'freigabe1u1 FROM ada LIMIT 0' at line 1 (1064).", - 156, + 155, ], ]; } elseif (PdoMysqlQueryReflector::NAME === getenv('DBA_REFLECTOR')) { @@ -198,11 +198,11 @@ public function testSyntaxErrorInQueryRule(): void ], [ "Query error: SQLSTATE[42000]: Syntax error or access violation: 1064 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 'freigabe1u1 FROM ada LIMIT 0' at line 1 (42000).", - 155, + 154, ], [ "Query error: SQLSTATE[42000]: Syntax error or access violation: 1064 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 'freigabe1u1 FROM ada LIMIT 0' at line 1 (42000).", - 156, + 155, ], ]; } elseif (PdoPgSqlQueryReflector::NAME === getenv('DBA_REFLECTOR')) { @@ -319,13 +319,13 @@ public function testSyntaxErrorInQueryRule(): void 'Query error: SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "freigabe1u1" LINE 1: SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada LIMIT... ^ (42601).', - 155, + 154, ], [ 'Query error: SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "freigabe1u1" LINE 1: SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada LIMIT... ^ (42601).', - 156, + 155, ], ]; } else { diff --git a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache index 4319ea1e1..3d0c8527b 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache @@ -133,7 +133,7 @@ Simulated query: SELECT * FROM 1 LIMIT 0', array ( 'error' => \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'doesNotExist\' in \'GROUP BY\'', + 'message' => 'Unknown column \'doesNotExist\' in \'group statement\'', 'code' => 1054, )), ), @@ -141,7 +141,7 @@ Simulated query: SELECT * FROM 1 LIMIT 0', array ( 'error' => \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'doesNotExist\' in \'ORDER BY\'', + 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', 'code' => 1054, )), ), @@ -159,7 +159,7 @@ Simulated query: SELECT * FROM 1 LIMIT 0', array ( 'error' => \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'doesNotExist\' in \'WHERE\'', + 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', 'code' => 1054, )), ), @@ -265,7 +265,7 @@ Simulated query: SELECT FROM WHERE LIMIT 0', array ( 'error' => \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'doesNotExist\' in \'SELECT\'', + 'message' => 'Unknown column \'doesNotExist\' in \'field list\'', 'code' => 1054, )), ), @@ -362,7 +362,7 @@ Simulated query: SELECT FROM WHERE LIMIT 0', array ( 'error' => \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'xy\' in \'GROUP BY\'', + 'message' => 'Unknown column \'xy\' in \'group statement\'', 'code' => 1054, )), ), @@ -480,7 +480,7 @@ Simulated query: SELECT FROM WHERE LIMIT 0', array ( 'error' => \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'asdsa\' in \'WHERE\'', + 'message' => 'Unknown column \'asdsa\' in \'where clause\'', 'code' => 1054, )), ), @@ -488,7 +488,7 @@ Simulated query: SELECT FROM WHERE LIMIT 0', array ( 'error' => \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'asdsa\' in \'WHERE\'', + 'message' => 'Unknown column \'asdsa\' in \'where clause\'', 'code' => 1054, )), ), @@ -506,7 +506,7 @@ Simulated query: SELECT FROM WHERE LIMIT 0', array ( 'error' => \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'does_not_exist\' in \'SELECT\'', + 'message' => 'Unknown column \'does_not_exist\' in \'field list\'', 'code' => 1054, )), ), @@ -514,7 +514,7 @@ Simulated query: SELECT FROM WHERE LIMIT 0', array ( 'error' => \staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'does_not_exist\' in \'SELECT\'', + 'message' => 'Unknown column \'does_not_exist\' in \'field list\'', 'code' => 1054, )), ), diff --git a/tests/sqlAst/config/.phpunit-phpstan-dba-mysqli.cache b/tests/sqlAst/config/.phpunit-phpstan-dba-mysqli.cache index f8bd47ad5..2541ea5e9 100644 --- a/tests/sqlAst/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/sqlAst/config/.phpunit-phpstan-dba-mysqli.cache @@ -74,7 +74,7 @@ array ( 5 => array ( - 'type-description' => 'array{3: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', + 'type-description' => 'array{3: int, 0: int}', ), ), ), @@ -84,7 +84,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', + 'type-description' => 'array{col: int, 0: int}', ), ), ), @@ -114,7 +114,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', + 'type-description' => 'array{col: int, 0: int}', ), ), ), @@ -134,7 +134,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int<-2147483648, 2147483647>|null, 0: int<-2147483648, 2147483647>|null}', + 'type-description' => 'array{col: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', ), ), ), @@ -144,7 +144,7 @@ array ( 5 => array ( - 'type-description' => 'array{field: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', + 'type-description' => 'array{field: int, 0: int}', ), ), ), @@ -224,7 +224,7 @@ array ( 5 => array ( - 'type-description' => 'array{abs: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', + 'type-description' => 'array{abs: int, 0: int}', ), ), ), @@ -724,7 +724,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int<-2147483648, 2147483647>|null, 0: int<-2147483648, 2147483647>|null}', + 'type-description' => 'array{col: int|null, 0: int|null}', ), ), ), @@ -734,7 +734,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int<-2147483648, 2147483647>|null, 0: int<-2147483648, 2147483647>|null}', + 'type-description' => 'array{col: int|null, 0: int|null}', ), ), ), @@ -974,7 +974,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', + 'type-description' => 'array{col: int, 0: int}', ), ), ), @@ -1044,7 +1044,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: mixed, 0: mixed}', + 'type-description' => 'array{col: string|null, 0: string|null}', ), ), ), @@ -1054,7 +1054,7 @@ array ( 5 => array ( - 'type-description' => 'array{field: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', + 'type-description' => 'array{field: int, 0: int}', ), ), ), @@ -1064,7 +1064,7 @@ array ( 5 => array ( - 'type-description' => 'array{field: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', + 'type-description' => 'array{field: int, 0: int}', ), ), ), @@ -1074,7 +1074,7 @@ array ( 5 => array ( - 'type-description' => 'array{field: int<-2147483648, 2147483647>|null, 0: int<-2147483648, 2147483647>|null}', + 'type-description' => 'array{field: int|null, 0: int|null}', ), ), ), @@ -1084,7 +1084,7 @@ array ( 5 => array ( - 'type-description' => 'array{n1: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', + 'type-description' => 'array{n1: int, 0: int}', ), ), ), @@ -1094,7 +1094,7 @@ array ( 5 => array ( - 'type-description' => 'array{n1: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', + 'type-description' => 'array{n1: int, 0: int}', ), ), ), @@ -1114,7 +1114,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', + 'type-description' => 'array{col: int, 0: int}', ), ), ), @@ -1124,7 +1124,7 @@ array ( 5 => array ( - 'type-description' => 'array{field: int<-2147483648, 2147483647>|null, 0: int<-2147483648, 2147483647>|null}', + 'type-description' => 'array{field: int|null, 0: int|null}', ), ), ), @@ -1134,7 +1134,7 @@ array ( 5 => array ( - 'type-description' => 'array{field: int<-2147483648, 2147483647>, 0: int<-2147483648, 2147483647>}', + 'type-description' => 'array{field: int, 0: int}', ), ), ), @@ -1144,7 +1144,7 @@ array ( 5 => array ( - 'type-description' => 'array{field: int<-2147483648, 2147483647>|null, 0: int<-2147483648, 2147483647>|null}', + 'type-description' => 'array{field: int|null, 0: int|null}', ), ), ), @@ -1284,7 +1284,7 @@ array ( 5 => array ( - 'type-description' => 'array{max: string|null, 0: string|null}', + 'type-description' => 'array{max: mixed, 0: mixed}', ), ), ), @@ -1354,7 +1354,7 @@ array ( 5 => array ( - 'type-description' => 'array{min: string|null, 0: string|null}', + 'type-description' => 'array{min: mixed, 0: mixed}', ), ), ), @@ -1364,7 +1364,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int<-2147483648, 2147483647>|null, 0: int<-2147483648, 2147483647>|null}', + 'type-description' => 'array{col: int|null, 0: int|null}', ), ), ), @@ -1374,7 +1374,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int<-2147483648, 2147483647>|null, 0: int<-2147483648, 2147483647>|null}', + 'type-description' => 'array{col: int|null, 0: int|null}', ), ), ), @@ -1444,7 +1444,7 @@ array ( 5 => array ( - 'type-description' => 'array{col: int<-2147483648, 2147483647>|null, 0: int<-2147483648, 2147483647>|null}', + 'type-description' => 'array{col: int|null, 0: int|null}', ), ), ), @@ -1464,7 +1464,7 @@ array ( 5 => array ( - 'type-description' => 'array{abs: int<-32768, 32767>, 0: int<-32768, 32767>}', + 'type-description' => 'array{abs: int, 0: int}', ), ), ), From 665c5a093f4889e7157bda187d0f1bc80d8f9e57 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 7 Aug 2025 11:24:57 +0200 Subject: [PATCH 7/9] re-record --- .phpstan-dba-pdo-mysql.cache | 31 +++++++++++++++++++ .../config/.phpunit-phpstan-dba-mysqli.cache | 8 +++++ .../.phpunit-phpstan-dba-pdo-mysql.cache | 8 +++++ tests/rules/QueryPlanAnalyzerRuleTest.php | 4 +-- 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/.phpstan-dba-pdo-mysql.cache b/.phpstan-dba-pdo-mysql.cache index 3e5688b32..888331abd 100644 --- a/.phpstan-dba-pdo-mysql.cache +++ b/.phpstan-dba-pdo-mysql.cache @@ -3,6 +3,21 @@ 'schemaHash' => '72813316a311d2e2b9384c458247d011', 'records' => array ( + 'SELECT + coalesce(COLUMN_NAME, \'\') as COLUMN_NAME, + coalesce(EXTRA, \'\') as EXTRA, + COLUMN_TYPE + FROM information_schema.columns + WHERE table_name = \'1970-01-01\' AND table_schema = DATABASE()' => + array ( + 'result' => + array ( + 5 => + array ( + 'type-description' => 'array{COLUMN_NAME: string, 0: string, EXTRA: string, 1: string, COLUMN_TYPE: string, 2: string}', + ), + ), + ), 'SELECT MD5( GROUP_CONCAT( @@ -33,6 +48,22 @@ array ( 'type-description' => 'array{dbsignature: string|null, 0: string|null, grouper: int, 1: int}', ), + 3 => + array ( + 'type-description' => 'array{dbsignature: string|null, grouper: int}', + ), + ), + ), + 'SELECT column_name, column_default, is_nullable + FROM information_schema.columns + WHERE table_name = \'1970-01-01\'' => + array ( + 'result' => + array ( + 5 => + array ( + 'type-description' => 'array{COLUMN_NAME: string|null, 0: string|null, COLUMN_DEFAULT: string|null, 1: string|null, IS_NULLABLE: string, 2: string}', + ), ), ), ), diff --git a/tests/default/config/.phpunit-phpstan-dba-mysqli.cache b/tests/default/config/.phpunit-phpstan-dba-mysqli.cache index a0ad7902e..e1fab7416 100644 --- a/tests/default/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/default/config/.phpunit-phpstan-dba-mysqli.cache @@ -300,6 +300,10 @@ FROM ada' => array ( 'type-description' => 'array{email: string, 0: string}', ), + 3 => + array ( + 'type-description' => 'array{email: string}', + ), ), ), 'SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada' => @@ -318,6 +322,10 @@ FROM ada' => array ( 'type-description' => 'array{email: string, 0: string, adaid: int<-32768, 32767>, 1: int<-32768, 32767>}', ), + 3 => + array ( + 'type-description' => 'array{email: string, adaid: int<-32768, 32767>}', + ), ), ), 'SELECT email, adaid FROM ada LIMIT 1' => diff --git a/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache b/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache index d4f38badf..1c7b3a8d9 100644 --- a/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache +++ b/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache @@ -300,6 +300,10 @@ FROM ada' => array ( 'type-description' => 'array{email: string, 0: string}', ), + 3 => + array ( + 'type-description' => 'array{email: string}', + ), ), ), 'SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada' => @@ -318,6 +322,10 @@ FROM ada' => array ( 'type-description' => 'array{email: string, 0: string, adaid: int<-32768, 32767>, 1: int<-32768, 32767>}', ), + 3 => + array ( + 'type-description' => 'array{email: string, adaid: int<-32768, 32767>}', + ), ), ), 'SELECT email, adaid FROM ada LIMIT 1' => diff --git a/tests/rules/QueryPlanAnalyzerRuleTest.php b/tests/rules/QueryPlanAnalyzerRuleTest.php index cafc4be3b..c9641ea82 100644 --- a/tests/rules/QueryPlanAnalyzerRuleTest.php +++ b/tests/rules/QueryPlanAnalyzerRuleTest.php @@ -174,12 +174,12 @@ public function testNotUsingIndexInDebugMode(): void UnresolvableQueryStringTypeException::getTip(), ], [ - "Query is not using an index on table 'ada'." . $proposal, + "Query is not using an index on table 'ada'." . $proposal . "\n\nSimulated query: EXPLAIN SELECT * FROM `ada` WHERE email = 'test@example.com'", 78, $tip, ], [ - "Query is not using an index on table 'ada'." . $proposal, + "Query is not using an index on table 'ada'." . $proposal . "\n\nSimulated query: EXPLAIN SELECT *,adaid FROM `ada` WHERE email = 'test@example.com'", 79, $tip, ], From d12d7dd85d5588323d4856e0e5c074f4dfba2f93 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 7 Aug 2025 11:27:28 +0200 Subject: [PATCH 8/9] fix pgsql --- tests/rules/SyntaxErrorInPreparedStatementMethodRuleTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/rules/SyntaxErrorInPreparedStatementMethodRuleTest.php b/tests/rules/SyntaxErrorInPreparedStatementMethodRuleTest.php index ab33f41f5..6c0454c32 100644 --- a/tests/rules/SyntaxErrorInPreparedStatementMethodRuleTest.php +++ b/tests/rules/SyntaxErrorInPreparedStatementMethodRuleTest.php @@ -188,7 +188,9 @@ public function testSyntaxErrorInQueryRule(): void 388, ], [ - "Query error: Unknown column 'asdsa' in 'where clause' (1054).", + 'Query error: SQLSTATE[42703]: Undefined column: 7 ERROR: column "asdsa" does not exist +LINE 1: ...mail, adaid, gesperrt, freigabe1u1 FROM ada WHERE asdsa=\'1\' ... + ^ (42703).', 389, ], ]; From 6526b601610643b6e431cd2f7e15bf8600f3f6d7 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 7 Aug 2025 11:30:39 +0200 Subject: [PATCH 9/9] Update SyntaxErrorInPreparedStatementMethodRuleTest.php --- tests/rules/SyntaxErrorInPreparedStatementMethodRuleTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/rules/SyntaxErrorInPreparedStatementMethodRuleTest.php b/tests/rules/SyntaxErrorInPreparedStatementMethodRuleTest.php index 6c0454c32..8826cfb6c 100644 --- a/tests/rules/SyntaxErrorInPreparedStatementMethodRuleTest.php +++ b/tests/rules/SyntaxErrorInPreparedStatementMethodRuleTest.php @@ -99,7 +99,7 @@ public function testSyntaxErrorInQueryRule(): void 388, ], [ - "Query error: Unknown column 'asdsa' in 'where clause' (1054).", + $error, 389, ], ];