From 945c0a76b3a005b363caa859f9ac1e612a82587f Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 22 May 2022 11:24:49 +0200 Subject: [PATCH 01/24] query plan analyzer --- src/Analyzer/QueryPlanAnalyzerMysql.php | 67 ++++++++++++ src/Analyzer/QueryPlanResult.php | 50 +++++++++ src/QueryReflection/QueryReflection.php | 17 +++ src/QueryReflection/QueryResolver.php | 38 +++++++ src/Rules/QueryPlanAnalyzerRule.php | 134 ++++++++++++++++++++++++ 5 files changed, 306 insertions(+) create mode 100644 src/Analyzer/QueryPlanAnalyzerMysql.php create mode 100644 src/Analyzer/QueryPlanResult.php create mode 100644 src/QueryReflection/QueryResolver.php create mode 100644 src/Rules/QueryPlanAnalyzerRule.php diff --git a/src/Analyzer/QueryPlanAnalyzerMysql.php b/src/Analyzer/QueryPlanAnalyzerMysql.php new file mode 100644 index 000000000..a2b52429b --- /dev/null +++ b/src/Analyzer/QueryPlanAnalyzerMysql.php @@ -0,0 +1,67 @@ +connection = $connection; + } + + /** + * @param non-empty-string $query + * @return QueryPlanResult + */ + public function analyze(string $query):QueryPlanResult { + + if ($this->connection instanceof PDO) { + $stmt = $this->connection->query('EXPLAIN '. $query); + + return $this->buildResult($stmt); + + } else { + $result = $this->connection->query('EXPLAIN '. $query); + if ($result instanceof \mysqli_result) { + return $this->buildResult($result); + } + } + + throw new ShouldNotHappenException(); + } + + /** + * @param \Iterator $it + * @return QueryPlanResult + */ + private function buildResult(\Iterator $it):QueryPlanResult { + $result = new QueryPlanResult(); + + foreach ($it as $row) { + // XXX is $row mixed? + if (!is_array($row) || !array_key_exists('table', $row) || !array_key_exists('rows', $row) || !array_key_exists('key', $row)) { + throw new ShouldNotHappenException(); + } + + if ($row['key'] === null) { + $result->addRow($row['table'], QueryPlanResult::NO_INDDEX); + }elseif ($row['rows'] > 100000) { + $result->addRow($row['table'], QueryPlanResult::NOT_EFFIECIENT); + } + } + + return $result; + } +} diff --git a/src/Analyzer/QueryPlanResult.php b/src/Analyzer/QueryPlanResult.php new file mode 100644 index 000000000..bada75f91 --- /dev/null +++ b/src/Analyzer/QueryPlanResult.php @@ -0,0 +1,50 @@ + + */ + private $result = []; + + /** + * @param string $table + * @param self::* $result + * @return void + */ + public function addRow(string $table, string $result) { + $this->result[$table] = $result; + } + + /** + * @return string[] + */ + public function getTablesNotUsingIndex():array { + $tables = []; + foreach($this->result as $table => $result) { + if ($result === self::NO_INDDEX) { + $tables[] = $table; + } + } + return $tables; + } + + /** + * @return string[] + */ + public function getTablesNotEfficient():array { + $tables = []; + foreach($this->result as $table => $result) { + if ($result === self::NOT_EFFIECIENT) { + $tables[] = $table; + } + } + return $tables; + } +} diff --git a/src/QueryReflection/QueryReflection.php b/src/QueryReflection/QueryReflection.php index a32891d0b..af76dd062 100644 --- a/src/QueryReflection/QueryReflection.php +++ b/src/QueryReflection/QueryReflection.php @@ -14,8 +14,11 @@ use PHPStan\Type\Type; use PHPStan\Type\TypeUtils; use PHPStan\Type\UnionType; +use staabm\PHPStanDba\Analyzer\QueryPlanAnalyzerMysql; +use staabm\PHPStanDba\Analyzer\QueryPlanResult; use staabm\PHPStanDba\DbaException; use staabm\PHPStanDba\Error; +use staabm\PHPStanDba\Rules\QueryPlanAnalyzerRule; use staabm\PHPStanDba\UnresolvableQueryException; final class QueryReflection @@ -399,4 +402,18 @@ public function extractNamedPlaceholders(string $queryString): array return []; } + + /** + * @return iterable + */ + public function analyzeQueryPlan(Scope $scope, Expr $queryExpr, ?Type $parameterTypes): iterable { + $reflector = self::reflector(); + + $queryResolver = new QueryResolver(); + $queryPlanAnalyzer = new QueryPlanAnalyzerMysql(); + + foreach($queryResolver->resolve($scope, $queryExpr, $parameterTypes) as $queryString) { + yield $queryPlanAnalyzer->analyze($queryString); + } + } } diff --git a/src/QueryReflection/QueryResolver.php b/src/QueryReflection/QueryResolver.php new file mode 100644 index 000000000..2ab0ff589 --- /dev/null +++ b/src/QueryReflection/QueryResolver.php @@ -0,0 +1,38 @@ + + * + * @throws UnresolvableQueryException + */ + public function resolve(Scope $scope, Expr $queryExpr, ?Type $parameterTypes):iterable { + $queryReflection = new QueryReflection(); + + $parameters = null; + if ($parameterTypes !== null) { + $parameters = $queryReflection->resolveParameters($parameterTypes) ?? []; + } + + if (null === $parameters) { + $queryStrings = $queryReflection->resolveQueryStrings($queryExpr, $scope); + } else { + $queryStrings = $queryReflection->resolvePreparedQueryStrings($queryExpr, $parameterTypes, $scope); + } + + foreach ($queryStrings as $queryString) { + yield $queryString; + } + } + +} diff --git a/src/Rules/QueryPlanAnalyzerRule.php b/src/Rules/QueryPlanAnalyzerRule.php new file mode 100644 index 000000000..0861f4623 --- /dev/null +++ b/src/Rules/QueryPlanAnalyzerRule.php @@ -0,0 +1,134 @@ + + */ +final class QueryPlanAnalyzerRule implements Rule +{ + /** + * @var list + */ + private $classMethods; + + /** + * @param list $classMethods + */ + public function __construct(array $classMethods) + { + $this->classMethods = $classMethods; + } + + public function getNodeType(): string + { + return CallLike::class; + } + + public function processNode(Node $callLike, Scope $scope): array + { + if ($callLike instanceof MethodCall) { + if (!$callLike->name instanceof Node\Identifier) { + return []; + } + + $methodReflection = $scope->getMethodReflection($scope->getType($callLike->var), $callLike->name->toString()); + } elseif ($callLike instanceof New_) { + if (!$callLike->class instanceof FullyQualified) { + return []; + } + $methodReflection = $scope->getMethodReflection(new ObjectType($callLike->class->toCodeString()), '__construct'); + } else { + return []; + } + + if (null === $methodReflection) { + return []; + } + + $unsupportedMethod = true; + foreach ($this->classMethods as $classMethod) { + sscanf($classMethod, '%[^::]::%s', $className, $methodName); + + if ($methodName === $methodReflection->getName() && + ($methodReflection->getDeclaringClass()->getName() === $className || $methodReflection->getDeclaringClass()->isSubclassOf($className))) { + $unsupportedMethod = false; + break; + } + } + + if ($unsupportedMethod) { + return []; + } + + return $this->analyze($callLike, $scope); + } + + /** + * @param MethodCall|New_ $callLike + * + * @return RuleError[] + */ + private function analyze(CallLike $callLike, Scope $scope): array + { + $args = $callLike->getArgs(); + + if (\count($args) < 1) { + return []; + } + + $queryExpr = $args[0]->value; + + if ($scope->getType($queryExpr) instanceof MixedType) { + return []; + } + + $parameterTypes = null; + if (\count($args) > 1) { + $parameterTypes = $scope->getType($args[1]->value); + } + + $errors = []; + $queryReflection = new QueryReflection(); + foreach($queryReflection->analyzeQueryPlan($scope, $queryExpr, $parameterTypes) as $queryPlanResult) { + $notUsingIndex = $queryPlanResult->getTablesNotUsingIndex(); + if (count($notUsingIndex)> 0) { + foreach($notUsingIndex as $table) { + $errors[] = sprintf('Query plan analyzer: table "%s" is not using an index', $table); + } + + } else { + foreach($queryPlanResult->getTablesNotEfficient() as $table) { + $errors[] = sprintf('Query plan analyzer: in efficient index use in table "%s"', $table); + } + } + } + + $ruleErrors = []; + foreach ($errors as $error) { + $ruleErrors[] = RuleErrorBuilder::message($error)->line($callLike->getLine())->build(); + } + + return $ruleErrors; + } + +} From 170190a6b6966ac55615b7ecaf39cfabaf6719c5 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 22 May 2022 11:47:53 +0200 Subject: [PATCH 02/24] wip --- config/dba.neon | 12 ++ src/QueryReflection/BasePdoQueryReflector.php | 4 + src/QueryReflection/MysqliQueryReflector.php | 5 + src/QueryReflection/QueryReflection.php | 11 +- src/Rules/QueryPlanAnalyzerRule.php | 13 +- tests/rules/QueryPlanAnalyzerRuleTest.php | 36 +++++ .../config/.phpunit-phpstan-dba-mysqli.cache | 153 ++++++++++++++++++ tests/rules/config/query-plan-analyzer.neon | 12 ++ tests/rules/data/query-plan-analyzer.php | 9 ++ 9 files changed, 252 insertions(+), 3 deletions(-) create mode 100644 tests/rules/QueryPlanAnalyzerRuleTest.php create mode 100644 tests/rules/config/query-plan-analyzer.neon create mode 100644 tests/rules/data/query-plan-analyzer.php diff --git a/config/dba.neon b/config/dba.neon index eeb939704..cbf4faa3b 100644 --- a/config/dba.neon +++ b/config/dba.neon @@ -56,3 +56,15 @@ services: functionNames: - 'Deployer\runMysqlQuery#0' - 'mysqli_query#1' + + - + class: staabm\PHPStanDba\Rules\QueryPlanAnalyzerRule + tags: [phpstan.rules.rule] + arguments: + classMethods: + - 'PDO::query#0' + - 'PDO::prepare#0' + - 'mysqli::query#0' + - 'Doctrine\DBAL\Connection::query#0' # deprecated in doctrine + - 'Doctrine\DBAL\Connection::exec#0' # deprecated in doctrine + # TODO diff --git a/src/QueryReflection/BasePdoQueryReflector.php b/src/QueryReflection/BasePdoQueryReflector.php index e43d57113..58ef7a0e5 100644 --- a/src/QueryReflection/BasePdoQueryReflector.php +++ b/src/QueryReflection/BasePdoQueryReflector.php @@ -156,6 +156,10 @@ protected function emulateFlags(string $nativeType, string $tableName, string $c return $this->emulateFlags($nativeType, $tableName, $columnName); } + public function getPDO():PDO { + return $this->pdo; + } + /** @return PDOException|list|null */ abstract protected function simulateQuery(string $queryString); diff --git a/src/QueryReflection/MysqliQueryReflector.php b/src/QueryReflection/MysqliQueryReflector.php index b5be93086..2ec66c603 100644 --- a/src/QueryReflection/MysqliQueryReflector.php +++ b/src/QueryReflection/MysqliQueryReflector.php @@ -150,4 +150,9 @@ private function simulateQuery(string $queryString) $this->db->rollback(); } } + + public function getMysqli(): mysqli + { + return $this->db; + } } diff --git a/src/QueryReflection/QueryReflection.php b/src/QueryReflection/QueryReflection.php index af76dd062..e44235e10 100644 --- a/src/QueryReflection/QueryReflection.php +++ b/src/QueryReflection/QueryReflection.php @@ -409,9 +409,16 @@ public function extractNamedPlaceholders(string $queryString): array public function analyzeQueryPlan(Scope $scope, Expr $queryExpr, ?Type $parameterTypes): iterable { $reflector = self::reflector(); - $queryResolver = new QueryResolver(); - $queryPlanAnalyzer = new QueryPlanAnalyzerMysql(); + // XXX overhaul + if ($reflector instanceof BasePdoQueryReflector) { + $queryPlanAnalyzer = new QueryPlanAnalyzerMysql($reflector->getPDO()); + } elseif ($reflector instanceof MysqliQueryReflector) { + $queryPlanAnalyzer = new QueryPlanAnalyzerMysql($reflector->getMysqli()); + } else { + throw new DbaException('Unsupported query reflector: '.get_class($reflector)); + } + $queryResolver = new QueryResolver(); foreach($queryResolver->resolve($scope, $queryExpr, $parameterTypes) as $queryString) { yield $queryPlanAnalyzer->analyze($queryString); } diff --git a/src/Rules/QueryPlanAnalyzerRule.php b/src/Rules/QueryPlanAnalyzerRule.php index 0861f4623..d81562353 100644 --- a/src/Rules/QueryPlanAnalyzerRule.php +++ b/src/Rules/QueryPlanAnalyzerRule.php @@ -66,8 +66,9 @@ public function processNode(Node $callLike, Scope $scope): array } $unsupportedMethod = true; + $queryArgPosition = null; foreach ($this->classMethods as $classMethod) { - sscanf($classMethod, '%[^::]::%s', $className, $methodName); + sscanf($classMethod, '%[^::]::%[^#]#%s', $className, $methodName, $queryArgPosition); if ($methodName === $methodReflection->getName() && ($methodReflection->getDeclaringClass()->getName() === $className || $methodReflection->getDeclaringClass()->isSubclassOf($className))) { @@ -80,6 +81,16 @@ public function processNode(Node $callLike, Scope $scope): array return []; } + $args = $callLike->getArgs(); + + if (!\array_key_exists($queryArgPosition, $args)) { + return []; + } + + if ($scope->getType($args[$queryArgPosition]->value) instanceof MixedType) { + return []; + } + return $this->analyze($callLike, $scope); } diff --git a/tests/rules/QueryPlanAnalyzerRuleTest.php b/tests/rules/QueryPlanAnalyzerRuleTest.php new file mode 100644 index 000000000..122dbbd65 --- /dev/null +++ b/tests/rules/QueryPlanAnalyzerRuleTest.php @@ -0,0 +1,36 @@ + + */ +class QueryPlanAnalyzerRuleTest extends RuleTestCase +{ + protected function getRule(): Rule + { + return self::getContainer()->getByType(QueryPlanAnalyzerRule::class); + } + + public static function getAdditionalConfigFiles(): array + { + return [ + __DIR__.'/config/query-plan-analyzer.neon', + ]; + } + + public function testParameterErrors(): void + { + $this->analyse([__DIR__.'/data/query-plan-analyzer.php'], [ + [ + 'Query expects placeholder :adaid, but it is missing from values given.', + 12, + ], + ]); + } +} diff --git a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache index 6dc394048..60cc90353 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache @@ -206,6 +206,159 @@ array ( 'error' => NULL, ), + 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), 'SELECT * FROM ada GROUP BY doesNotExist' => array ( 'error' => diff --git a/tests/rules/config/query-plan-analyzer.neon b/tests/rules/config/query-plan-analyzer.neon new file mode 100644 index 000000000..257c88070 --- /dev/null +++ b/tests/rules/config/query-plan-analyzer.neon @@ -0,0 +1,12 @@ +includes: + - ../../../config/stubFiles.neon + - ../../../config/extensions.neon + +services: + - + class: staabm\PHPStanDba\Rules\QueryPlanAnalyzerRule + tags: [phpstan.rules.rule] + arguments: + classMethods: + - 'PDO::query#0' + - 'PDO::prepare#0' diff --git a/tests/rules/data/query-plan-analyzer.php b/tests/rules/data/query-plan-analyzer.php new file mode 100644 index 000000000..d9f00afaa --- /dev/null +++ b/tests/rules/data/query-plan-analyzer.php @@ -0,0 +1,9 @@ +query("SELECT * FROM `ada` WHERE email = 'test@example.com';"); + } +} From 5fe356d824a49a263e96e667b43a188fd76d0e37 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Mon, 23 May 2022 10:09:04 +0200 Subject: [PATCH 03/24] Create RecordingReflector.php --- src/QueryReflection/RecordingReflector.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/QueryReflection/RecordingReflector.php diff --git a/src/QueryReflection/RecordingReflector.php b/src/QueryReflection/RecordingReflector.php new file mode 100644 index 000000000..77d90c6f7 --- /dev/null +++ b/src/QueryReflection/RecordingReflector.php @@ -0,0 +1,13 @@ + Date: Mon, 23 May 2022 10:11:34 +0200 Subject: [PATCH 04/24] fix --- src/Analyzer/QueryPlanAnalyzerMysql.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Analyzer/QueryPlanAnalyzerMysql.php b/src/Analyzer/QueryPlanAnalyzerMysql.php index a2b52429b..07dce3224 100644 --- a/src/Analyzer/QueryPlanAnalyzerMysql.php +++ b/src/Analyzer/QueryPlanAnalyzerMysql.php @@ -6,6 +6,7 @@ use PDO; use mysqli; +use PHPStan\ShouldNotHappenException; final class QueryPlanAnalyzerMysql { /** @@ -29,12 +30,13 @@ public function analyze(string $query):QueryPlanResult { if ($this->connection instanceof PDO) { $stmt = $this->connection->query('EXPLAIN '. $query); - + // @phpstan-ignore-next-line we cannot type the iterator return $this->buildResult($stmt); } else { $result = $this->connection->query('EXPLAIN '. $query); if ($result instanceof \mysqli_result) { + // @phpstan-ignore-next-line we cannot type the iterator return $this->buildResult($result); } } @@ -50,11 +52,6 @@ private function buildResult(\Iterator $it):QueryPlanResult { $result = new QueryPlanResult(); foreach ($it as $row) { - // XXX is $row mixed? - if (!is_array($row) || !array_key_exists('table', $row) || !array_key_exists('rows', $row) || !array_key_exists('key', $row)) { - throw new ShouldNotHappenException(); - } - if ($row['key'] === null) { $result->addRow($row['table'], QueryPlanResult::NO_INDDEX); }elseif ($row['rows'] > 100000) { From cf9dcb8b1b8e3f46f110c2728bf57ad32567f99c Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Mon, 23 May 2022 17:28:02 +0200 Subject: [PATCH 05/24] progress --- src/Analyzer/QueryPlanAnalyzerMysql.php | 15 +- src/Analyzer/QueryPlanResult.php | 8 +- src/QueryReflection/BasePdoQueryReflector.php | 5 +- src/QueryReflection/MysqliQueryReflector.php | 4 +- src/QueryReflection/QueryReflection.php | 15 +- .../RecordingQueryReflector.php | 10 +- src/QueryReflection/RecordingReflector.php | 7 +- .../ReplayAndRecordingQueryReflector.php | 7 +- .../config/.phpunit-phpstan-dba-mysqli.cache | 188 ++++++++++ tests/rules/QueryPlanAnalyzerRuleTest.php | 4 +- .../config/.phpunit-phpstan-dba-mysqli.cache | 335 +++++++++++++++--- 11 files changed, 527 insertions(+), 71 deletions(-) diff --git a/src/Analyzer/QueryPlanAnalyzerMysql.php b/src/Analyzer/QueryPlanAnalyzerMysql.php index 07dce3224..d2333c394 100644 --- a/src/Analyzer/QueryPlanAnalyzerMysql.php +++ b/src/Analyzer/QueryPlanAnalyzerMysql.php @@ -45,17 +45,22 @@ public function analyze(string $query):QueryPlanResult { } /** - * @param \Iterator $it + * @param \IteratorAggregate $it * @return QueryPlanResult */ - private function buildResult(\Iterator $it):QueryPlanResult { + private function buildResult(\IteratorAggregate $it):QueryPlanResult { $result = new QueryPlanResult(); foreach ($it as $row) { + // we cannot analyse tables without rows -> mysql will just return 'no matching row in const table' + if ($row['table'] === null) { + continue; + } + if ($row['key'] === null) { - $result->addRow($row['table'], QueryPlanResult::NO_INDDEX); - }elseif ($row['rows'] > 100000) { - $result->addRow($row['table'], QueryPlanResult::NOT_EFFIECIENT); + $result->addRow($row['table'], QueryPlanResult::NO_INDEX); + }elseif ($row['rows'] > 100000) { // XXX add RuntimeConfiguration + $result->addRow($row['table'], QueryPlanResult::NOT_EFFICIENT); } } diff --git a/src/Analyzer/QueryPlanResult.php b/src/Analyzer/QueryPlanResult.php index bada75f91..00562b60c 100644 --- a/src/Analyzer/QueryPlanResult.php +++ b/src/Analyzer/QueryPlanResult.php @@ -5,8 +5,8 @@ namespace staabm\PHPStanDba\Analyzer; final class QueryPlanResult { - const NO_INDDEX = "no-index"; - const NOT_EFFIECIENT = "inefficient"; + const NO_INDEX = "no-index"; + const NOT_EFFICIENT = "inefficient"; /** * @var array @@ -28,7 +28,7 @@ public function addRow(string $table, string $result) { public function getTablesNotUsingIndex():array { $tables = []; foreach($this->result as $table => $result) { - if ($result === self::NO_INDDEX) { + if ($result === self::NO_INDEX) { $tables[] = $table; } } @@ -41,7 +41,7 @@ public function getTablesNotUsingIndex():array { public function getTablesNotEfficient():array { $tables = []; foreach($this->result as $table => $result) { - if ($result === self::NOT_EFFIECIENT) { + if ($result === self::NOT_EFFICIENT) { $tables[] = $table; } } diff --git a/src/QueryReflection/BasePdoQueryReflector.php b/src/QueryReflection/BasePdoQueryReflector.php index 85e8c01d9..ad66eb167 100644 --- a/src/QueryReflection/BasePdoQueryReflector.php +++ b/src/QueryReflection/BasePdoQueryReflector.php @@ -18,7 +18,7 @@ /** * @phpstan-type ColumnMeta array{name: string, table: string, native_type: string, len: int, flags: array, precision: int<0, max>, pdo_type: PDO::PARAM_* } */ -abstract class BasePdoQueryReflector implements QueryReflector +abstract class BasePdoQueryReflector implements QueryReflector, RecordingReflector { private const PSQL_INVALID_TEXT_REPRESENTATION = '22P02'; private const PSQL_UNDEFINED_COLUMN = '42703'; @@ -156,7 +156,8 @@ protected function emulateFlags(string $nativeType, string $tableName, string $c return $this->emulateFlags($nativeType, $tableName, $columnName); } - public function getPDO():PDO { + public function getDatasource() + { return $this->pdo; } diff --git a/src/QueryReflection/MysqliQueryReflector.php b/src/QueryReflection/MysqliQueryReflector.php index 2ec66c603..584d24588 100644 --- a/src/QueryReflection/MysqliQueryReflector.php +++ b/src/QueryReflection/MysqliQueryReflector.php @@ -15,7 +15,7 @@ use staabm\PHPStanDba\Error; use staabm\PHPStanDba\TypeMapping\MysqliTypeMapper; -final class MysqliQueryReflector implements QueryReflector +final class MysqliQueryReflector implements QueryReflector, RecordingReflector { private const MYSQL_SYNTAX_ERROR_CODE = 1064; private const MYSQL_UNKNOWN_COLUMN_IN_FIELDLIST = 1054; @@ -151,7 +151,7 @@ private function simulateQuery(string $queryString) } } - public function getMysqli(): mysqli + public function getDatasource() { return $this->db; } diff --git a/src/QueryReflection/QueryReflection.php b/src/QueryReflection/QueryReflection.php index f4b43f901..61af61b76 100644 --- a/src/QueryReflection/QueryReflection.php +++ b/src/QueryReflection/QueryReflection.php @@ -417,15 +417,16 @@ public function extractNamedPlaceholders(string $queryString): array public function analyzeQueryPlan(Scope $scope, Expr $queryExpr, ?Type $parameterTypes): iterable { $reflector = self::reflector(); - // XXX overhaul - if ($reflector instanceof BasePdoQueryReflector) { - $queryPlanAnalyzer = new QueryPlanAnalyzerMysql($reflector->getPDO()); - } elseif ($reflector instanceof MysqliQueryReflector) { - $queryPlanAnalyzer = new QueryPlanAnalyzerMysql($reflector->getMysqli()); - } else { - throw new DbaException('Unsupported query reflector: '.get_class($reflector)); + if (!$reflector instanceof RecordingReflector) { + throw new DbaException('Query plan analysis is only supported with a recording reflector'); } + $ds = $reflector->getDatasource(); + if ($ds === null) { + throw new DbaException(sprintf('Unable to create datasource from %s', get_class($reflector))); + } + $queryPlanAnalyzer = new QueryPlanAnalyzerMysql($ds); + $queryResolver = new QueryResolver(); foreach($queryResolver->resolve($scope, $queryExpr, $parameterTypes) as $queryString) { yield $queryPlanAnalyzer->analyze($queryString); diff --git a/src/QueryReflection/RecordingQueryReflector.php b/src/QueryReflection/RecordingQueryReflector.php index 79320cce7..d1fa72135 100644 --- a/src/QueryReflection/RecordingQueryReflector.php +++ b/src/QueryReflection/RecordingQueryReflector.php @@ -7,7 +7,7 @@ use PHPStan\Type\Type; use staabm\PHPStanDba\Error; -final class RecordingQueryReflector implements QueryReflector +final class RecordingQueryReflector implements QueryReflector, RecordingReflector { /** * @var ReflectionCache @@ -54,4 +54,12 @@ public function getResultType(string $queryString, int $fetchType): ?Type return $resultType; } + + public function getDatasource() + { + if ($this->reflector instanceof RecordingReflector) { + return $this->reflector->getDatasource(); + } + return null; + } } diff --git a/src/QueryReflection/RecordingReflector.php b/src/QueryReflection/RecordingReflector.php index 77d90c6f7..aed2b0d45 100644 --- a/src/QueryReflection/RecordingReflector.php +++ b/src/QueryReflection/RecordingReflector.php @@ -7,7 +7,12 @@ interface RecordingReflector { /** - * @return \mysqli|\PDO + * Returns the underlying datasource of a reflector. + * + * Beware this might establish a database connection, in case a reflector is implemented lazily. + * Therefore calling this method might have a negative performance impact. + * + * @return \mysqli|\PDO|null */ public function getDatasource(); } diff --git a/src/QueryReflection/ReplayAndRecordingQueryReflector.php b/src/QueryReflection/ReplayAndRecordingQueryReflector.php index adcd2b598..7acc3a6c3 100644 --- a/src/QueryReflection/ReplayAndRecordingQueryReflector.php +++ b/src/QueryReflection/ReplayAndRecordingQueryReflector.php @@ -9,7 +9,7 @@ use staabm\PHPStanDba\DbSchema\SchemaHasherMysql; use staabm\PHPStanDba\Error; -final class ReplayAndRecordingQueryReflector implements QueryReflector +final class ReplayAndRecordingQueryReflector implements QueryReflector, RecordingReflector { private ReplayQueryReflector $replayReflector; @@ -70,4 +70,9 @@ public function getResultType(string $queryString, int $fetchType): ?Type return $this->createRecordingReflector()->getResultType($queryString, $fetchType); } } + + public function getDatasource() + { + return $this->createRecordingReflector()->getDatasource(); + } } diff --git a/tests/default/config/.phpunit-phpstan-dba-mysqli.cache b/tests/default/config/.phpunit-phpstan-dba-mysqli.cache index f0209baca..18256a054 100644 --- a/tests/default/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/default/config/.phpunit-phpstan-dba-mysqli.cache @@ -3,6 +3,72 @@ 'schemaHash' => NULL, 'records' => array ( + 'SELECT + adaid + FROM + ada' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 1, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + )), + ), + ), 'SELECT adaid FROM @@ -1645,6 +1711,70 @@ ), ), 'SELECT adaid +FROM ada' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 1, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + )), + ), + ), + 'SELECT adaid FROM ada' => array ( 'result' => @@ -3052,6 +3182,64 @@ FROM ada' => ), ), 'SELECT email +FROM ada' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 1, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\StringType::__set_state(array( + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\StringType::__set_state(array( + )), + )), + ), + ), + 'SELECT email FROM ada' => array ( 'result' => diff --git a/tests/rules/QueryPlanAnalyzerRuleTest.php b/tests/rules/QueryPlanAnalyzerRuleTest.php index 122dbbd65..6eb85e570 100644 --- a/tests/rules/QueryPlanAnalyzerRuleTest.php +++ b/tests/rules/QueryPlanAnalyzerRuleTest.php @@ -28,8 +28,8 @@ public function testParameterErrors(): void { $this->analyse([__DIR__.'/data/query-plan-analyzer.php'], [ [ - 'Query expects placeholder :adaid, but it is missing from values given.', - 12, + 'Query plan analyzer: table "ada" is not using an index', + 7, ], ]); } diff --git a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache index d731f4753..18a26a62a 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache @@ -39,6 +39,195 @@ 5 => NULL, ), ), + 'SELECT + ada.*, + COALESCE(NULLIF(email, ""), email) AS email + FROM ada + INNER JOIN ak ON (ak.adaid = ada.adaid AND ak.akid = \'1\') + WHERE adaid = 1 ORDER BY COALESCE(NULLIF(email, ""), email) ASC' => + array ( + 'result' => + array ( + 5 => NULL, + ), + ), + 'SELECT + ada.*, + COALESCE(NULLIF(email, ""), email) AS email + FROM ada + INNER JOIN ak ON (ak.adaid = ada.adaid AND ak.akid = :akid) + WHERE adaid = 1 ORDER BY COALESCE(NULLIF(email, ""), email) ASC' => + array ( + 'result' => + array ( + 5 => NULL, + ), + ), + 'SELECT + ada.*, + COALESCE(NULLIF(email, ""), email) AS email + FROM ada + INNER JOIN ak ON (ak.adaid = ada.adaid AND ak.akid = ?) + WHERE adaid = 1 ORDER BY COALESCE(NULLIF(email, ""), email) ASC' => + array ( + 'result' => + array ( + 5 => NULL, + ), + ), + 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), 'SELECT * FROM ada GROUP BY doesNotExist' => array ( 'error' => @@ -46,10 +235,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'group statement\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -58,10 +243,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -70,10 +251,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM unknown_table' => array ( @@ -82,10 +259,6 @@ 'message' => 'Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => 1146, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT adaid FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -192,10 +365,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'field list\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email FROM ada WHERE adaid IN (\'1\')' => array ( @@ -223,6 +392,17 @@ 'code' => 1064, )), ), + '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', + 'code' => 1064, + )), + ), 'SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada' => array ( 'error' => @@ -230,11 +410,6 @@ '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', 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - 3 => NULL, - ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -243,10 +418,90 @@ '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', 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - ), + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' + FOR UPDATE' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' + LIMIT \'1\'' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' + LIMIT \'1\' + FOR UPDATE' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' + LIMIT \'1\' + OFFSET \'1\'' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' + LIMIT \'1\' + OFFSET \'1\' + FOR SHARE' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' + LIMIT \'1\' + OFFSET \'1\' + FOR UPDATE' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' + LIMIT \'1\' + OFFSET 1' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' + LIMIT \'1\', \'1\'' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' + LIMIT \'1\', \'1\'' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' AND email LIKE \'%@example%\' + LIMIT 1' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' AND email LIKE NULL + LIMIT 1' => + array ( + 'error' => NULL, ), 'SELECT email, adaid FROM ada @@ -339,10 +594,6 @@ 'message' => 'Unknown column \'xy\' in \'group statement\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada WHERE adaid = \'1\'' => array ( @@ -485,7 +736,6 @@ ), 'SELECT email, adaid FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -592,10 +842,6 @@ '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, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( @@ -606,7 +852,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada' => array ( - 'error' => NULL, 'result' => array ( 3 => @@ -860,9 +1105,13 @@ array ( 'error' => NULL, ), - 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada LIMIT 1' => + 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada + WHERE (gesperrt=\'1\' AND freigabe1u1=1) OR (gesperrt=\'1\' AND freigabe1u1=0)' => array ( 'error' => NULL, + ), + 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada LIMIT 1' => + array ( 'result' => array ( 5 => @@ -1016,7 +1265,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -1357,11 +1605,6 @@ 'message' => 'Unknown column \'asdsa\' in \'where clause\'', 'code' => 1054, )), - 'result' => - array ( - 3 => NULL, - 5 => NULL, - ), ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE gesperrt=\'1\'' => array ( From 0f469e5bdc7afb91478863d49a4ef51259783757 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Mon, 23 May 2022 17:39:46 +0200 Subject: [PATCH 06/24] cleanup --- .phpstan-dba-pdo-mysql.cache | 479 ++++++++++++++++- src/Analyzer/QueryPlanAnalyzerMysql.php | 28 +- src/Analyzer/QueryPlanResult.php | 28 +- src/QueryReflection/QueryReflection.php | 13 +- src/QueryReflection/QueryResolver.php | 10 +- .../RecordingQueryReflector.php | 1 + src/Rules/QueryPlanAnalyzerRule.php | 14 +- .../default/config/.phpstan-dba-mysqli.cache | 188 +++++++ .../config/.phpstan-dba-pdo-mysql.cache | 188 +++++++ .../.phpunit-phpstan-dba-pdo-mysql.cache | 188 +++++++ tests/rules/QueryPlanAnalyzerRuleTest.php | 3 +- tests/rules/config/.phpstan-dba-mysqli.cache | 342 ++++++++++++ .../rules/config/.phpstan-dba-pdo-mysql.cache | 342 ++++++++++++ .../config/.phpunit-phpstan-dba-mysqli.cache | 199 +++++++ .../.phpunit-phpstan-dba-pdo-mysql.cache | 488 ++++++++++++++++-- tests/rules/data/query-plan-analyzer.php | 9 +- 16 files changed, 2423 insertions(+), 97 deletions(-) diff --git a/.phpstan-dba-pdo-mysql.cache b/.phpstan-dba-pdo-mysql.cache index a89ac41e7..c5544ecca 100644 --- a/.phpstan-dba-pdo-mysql.cache +++ b/.phpstan-dba-pdo-mysql.cache @@ -332,6 +332,335 @@ )), ), ), + '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 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 3, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'COLUMN_NAME', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'EXTRA', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'COLUMN_TYPE', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\StringType::__set_state(array( + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + 2 => + PHPStan\Type\StringType::__set_state(array( + )), + 3 => + PHPStan\Type\StringType::__set_state(array( + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'COLUMN_NAME', + 'isClassString' => false, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'COLUMN_TYPE', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'EXTRA', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\StringType::__set_state(array( + )), + )), + ), + ), + 'SELECT + coalesce(COLUMN_NAME, "") as COLUMN_NAME, + coalesce(EXTRA, "") as EXTRA, + COLUMN_TYPE + FROM information_schema.columns + WHERE table_name = ? AND table_schema = DATABASE()' => + array ( + 'result' => + array ( + 5 => NULL, + ), + ), + 'SELECT + MD5( + GROUP_CONCAT( + CONCAT( + COALESCE(COLUMN_NAME, ""), + COALESCE(EXTRA, ""), + COLUMN_TYPE, + IS_NULLABLE + ) + ) + ) AS dbsignature, + 1 AS grouper + FROM + information_schema.columns + WHERE + table_schema = DATABASE() + GROUP BY + grouper' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 2, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'dbsignature', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'grouper', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\StringType::__set_state(array( + )), + 1 => + PHPStan\Type\NullType::__set_state(array( + )), + ), + )), + 1 => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\StringType::__set_state(array( + )), + 1 => + PHPStan\Type\NullType::__set_state(array( + )), + ), + )), + 2 => + PHPStan\Type\IntegerType::__set_state(array( + )), + 3 => + PHPStan\Type\IntegerType::__set_state(array( + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'dbsignature', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'grouper', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\StringType::__set_state(array( + )), + 1 => + PHPStan\Type\IntegerType::__set_state(array( + )), + 2 => + PHPStan\Type\NullType::__set_state(array( + )), + ), + )), + )), + 3 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 0, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'dbsignature', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'grouper', + 'isClassString' => false, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\StringType::__set_state(array( + )), + 1 => + PHPStan\Type\NullType::__set_state(array( + )), + ), + )), + 1 => + PHPStan\Type\IntegerType::__set_state(array( + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'dbsignature', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'grouper', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\StringType::__set_state(array( + )), + 1 => + PHPStan\Type\IntegerType::__set_state(array( + )), + 2 => + PHPStan\Type\NullType::__set_state(array( + )), + ), + )), + )), + ), + ), 'SELECT column_name, column_default, is_nullable FROM information_schema.columns WHERE table_name = \'1970-01-01\'' => @@ -385,7 +714,7 @@ WHERE table_name = \'1970-01-01\'' => )), 2 => PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => true, + 'sortedTypes' => false, 'types' => array ( 0 => @@ -398,7 +727,7 @@ WHERE table_name = \'1970-01-01\'' => )), 3 => PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => true, + 'sortedTypes' => false, 'types' => array ( 0 => @@ -454,9 +783,155 @@ WHERE table_name = \'1970-01-01\'' => ), )), 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\StringType::__set_state(array( + )), + 1 => + PHPStan\Type\NullType::__set_state(array( + )), + ), + )), + )), + ), + ), + 'SELECT column_name, column_default, is_nullable +FROM information_schema.columns +WHERE table_name = ?' => + array ( + 'result' => + array ( + 5 => NULL, + ), + ), + 'SELECT column_name, column_default, is_nullable +FROM information_schema.columns +WHERE table_name = \'1970-01-01\'' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 3, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'COLUMN_NAME', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'COLUMN_DEFAULT', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'IS_NULLABLE', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\StringType::__set_state(array( + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + 2 => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\StringType::__set_state(array( + )), + 1 => + PHPStan\Type\NullType::__set_state(array( + )), + ), + )), + 3 => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\StringType::__set_state(array( + )), + 1 => + PHPStan\Type\NullType::__set_state(array( + )), + ), + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => PHPStan\Type\UnionType::__set_state(array( 'sortedTypes' => true, 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'COLUMN_DEFAULT', + 'isClassString' => false, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'COLUMN_NAME', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'IS_NULLABLE', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => array ( 0 => PHPStan\Type\StringType::__set_state(array( diff --git a/src/Analyzer/QueryPlanAnalyzerMysql.php b/src/Analyzer/QueryPlanAnalyzerMysql.php index d2333c394..547533191 100644 --- a/src/Analyzer/QueryPlanAnalyzerMysql.php +++ b/src/Analyzer/QueryPlanAnalyzerMysql.php @@ -4,11 +4,12 @@ namespace staabm\PHPStanDba\Analyzer; -use PDO; use mysqli; +use PDO; use PHPStan\ShouldNotHappenException; -final class QueryPlanAnalyzerMysql { +final class QueryPlanAnalyzerMysql +{ /** * @var PDO|mysqli */ @@ -24,19 +25,16 @@ public function __construct($connection) /** * @param non-empty-string $query - * @return QueryPlanResult */ - public function analyze(string $query):QueryPlanResult { - + public function analyze(string $query): QueryPlanResult + { if ($this->connection instanceof PDO) { - $stmt = $this->connection->query('EXPLAIN '. $query); - // @phpstan-ignore-next-line we cannot type the iterator - return $this->buildResult($stmt); + $stmt = $this->connection->query('EXPLAIN '.$query); + return $this->buildResult($stmt); } else { - $result = $this->connection->query('EXPLAIN '. $query); + $result = $this->connection->query('EXPLAIN '.$query); if ($result instanceof \mysqli_result) { - // @phpstan-ignore-next-line we cannot type the iterator return $this->buildResult($result); } } @@ -46,20 +44,20 @@ public function analyze(string $query):QueryPlanResult { /** * @param \IteratorAggregate $it - * @return QueryPlanResult */ - private function buildResult(\IteratorAggregate $it):QueryPlanResult { + private function buildResult(\IteratorAggregate $it): QueryPlanResult + { $result = new QueryPlanResult(); foreach ($it as $row) { // we cannot analyse tables without rows -> mysql will just return 'no matching row in const table' - if ($row['table'] === null) { + if (null === $row['table']) { continue; } - if ($row['key'] === null) { + if (null === $row['key']) { $result->addRow($row['table'], QueryPlanResult::NO_INDEX); - }elseif ($row['rows'] > 100000) { // XXX add RuntimeConfiguration + } elseif ($row['rows'] > 100000) { // XXX add RuntimeConfiguration $result->addRow($row['table'], QueryPlanResult::NOT_EFFICIENT); } } diff --git a/src/Analyzer/QueryPlanResult.php b/src/Analyzer/QueryPlanResult.php index 00562b60c..140ddb80b 100644 --- a/src/Analyzer/QueryPlanResult.php +++ b/src/Analyzer/QueryPlanResult.php @@ -4,9 +4,10 @@ namespace staabm\PHPStanDba\Analyzer; -final class QueryPlanResult { - const NO_INDEX = "no-index"; - const NOT_EFFICIENT = "inefficient"; +final class QueryPlanResult +{ + public const NO_INDEX = 'no-index'; + public const NOT_EFFICIENT = 'inefficient'; /** * @var array @@ -14,37 +15,42 @@ final class QueryPlanResult { private $result = []; /** - * @param string $table * @param self::* $result + * * @return void */ - public function addRow(string $table, string $result) { + public function addRow(string $table, string $result) + { $this->result[$table] = $result; } /** * @return string[] */ - public function getTablesNotUsingIndex():array { + public function getTablesNotUsingIndex(): array + { $tables = []; - foreach($this->result as $table => $result) { - if ($result === self::NO_INDEX) { + foreach ($this->result as $table => $result) { + if (self::NO_INDEX === $result) { $tables[] = $table; } } + return $tables; } /** * @return string[] */ - public function getTablesNotEfficient():array { + public function getTablesNotEfficient(): array + { $tables = []; - foreach($this->result as $table => $result) { - if ($result === self::NOT_EFFICIENT) { + foreach ($this->result as $table => $result) { + if (self::NOT_EFFICIENT === $result) { $tables[] = $table; } } + return $tables; } } diff --git a/src/QueryReflection/QueryReflection.php b/src/QueryReflection/QueryReflection.php index 61af61b76..c5f7c4783 100644 --- a/src/QueryReflection/QueryReflection.php +++ b/src/QueryReflection/QueryReflection.php @@ -18,7 +18,6 @@ use staabm\PHPStanDba\Analyzer\QueryPlanResult; use staabm\PHPStanDba\DbaException; use staabm\PHPStanDba\Error; -use staabm\PHPStanDba\Rules\QueryPlanAnalyzerRule; use staabm\PHPStanDba\UnresolvableQueryException; final class QueryReflection @@ -414,7 +413,8 @@ public function extractNamedPlaceholders(string $queryString): array /** * @return iterable */ - public function analyzeQueryPlan(Scope $scope, Expr $queryExpr, ?Type $parameterTypes): iterable { + public function analyzeQueryPlan(Scope $scope, Expr $queryExpr, ?Type $parameterTypes): iterable + { $reflector = self::reflector(); if (!$reflector instanceof RecordingReflector) { @@ -422,13 +422,16 @@ public function analyzeQueryPlan(Scope $scope, Expr $queryExpr, ?Type $parameter } $ds = $reflector->getDatasource(); - if ($ds === null) { - throw new DbaException(sprintf('Unable to create datasource from %s', get_class($reflector))); + if (null === $ds) { + throw new DbaException(sprintf('Unable to create datasource from %s', \get_class($reflector))); } $queryPlanAnalyzer = new QueryPlanAnalyzerMysql($ds); $queryResolver = new QueryResolver(); - foreach($queryResolver->resolve($scope, $queryExpr, $parameterTypes) as $queryString) { + foreach ($queryResolver->resolve($scope, $queryExpr, $parameterTypes) as $queryString) { + if ('' === $queryString) { + continue; + } yield $queryPlanAnalyzer->analyze($queryString); } } diff --git a/src/QueryReflection/QueryResolver.php b/src/QueryReflection/QueryResolver.php index 2ab0ff589..45fe38b4b 100644 --- a/src/QueryReflection/QueryResolver.php +++ b/src/QueryReflection/QueryResolver.php @@ -5,22 +5,23 @@ namespace staabm\PHPStanDba\QueryReflection; use PhpParser\Node\Expr; -use PHPStan\Type\Type; use PHPStan\Analyser\Scope; +use PHPStan\Type\Type; use staabm\PHPStanDba\UnresolvableQueryException; final class QueryResolver { /** - * @return iterable + * @return iterable * * @throws UnresolvableQueryException */ - public function resolve(Scope $scope, Expr $queryExpr, ?Type $parameterTypes):iterable { + public function resolve(Scope $scope, Expr $queryExpr, ?Type $parameterTypes): iterable + { $queryReflection = new QueryReflection(); $parameters = null; - if ($parameterTypes !== null) { + if (null !== $parameterTypes) { $parameters = $queryReflection->resolveParameters($parameterTypes) ?? []; } @@ -34,5 +35,4 @@ public function resolve(Scope $scope, Expr $queryExpr, ?Type $parameterTypes):it yield $queryString; } } - } diff --git a/src/QueryReflection/RecordingQueryReflector.php b/src/QueryReflection/RecordingQueryReflector.php index d1fa72135..168b5594e 100644 --- a/src/QueryReflection/RecordingQueryReflector.php +++ b/src/QueryReflection/RecordingQueryReflector.php @@ -60,6 +60,7 @@ public function getDatasource() if ($this->reflector instanceof RecordingReflector) { return $this->reflector->getDatasource(); } + return null; } } diff --git a/src/Rules/QueryPlanAnalyzerRule.php b/src/Rules/QueryPlanAnalyzerRule.php index d81562353..08398388f 100644 --- a/src/Rules/QueryPlanAnalyzerRule.php +++ b/src/Rules/QueryPlanAnalyzerRule.php @@ -15,11 +15,7 @@ use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Type\MixedType; use PHPStan\Type\ObjectType; -use staabm\PHPStanDba\Analyzer\QueryPlanAnalyzerMysql; -use staabm\PHPStanDba\QueryReflection\PlaceholderValidation; use staabm\PHPStanDba\QueryReflection\QueryReflection; -use staabm\PHPStanDba\QueryReflection\QueryResolver; -use staabm\PHPStanDba\UnresolvableQueryException; /** * @implements Rule @@ -120,15 +116,14 @@ private function analyze(CallLike $callLike, Scope $scope): array $errors = []; $queryReflection = new QueryReflection(); - foreach($queryReflection->analyzeQueryPlan($scope, $queryExpr, $parameterTypes) as $queryPlanResult) { + foreach ($queryReflection->analyzeQueryPlan($scope, $queryExpr, $parameterTypes) as $queryPlanResult) { $notUsingIndex = $queryPlanResult->getTablesNotUsingIndex(); - if (count($notUsingIndex)> 0) { - foreach($notUsingIndex as $table) { + if (\count($notUsingIndex) > 0) { + foreach ($notUsingIndex as $table) { $errors[] = sprintf('Query plan analyzer: table "%s" is not using an index', $table); } - } else { - foreach($queryPlanResult->getTablesNotEfficient() as $table) { + foreach ($queryPlanResult->getTablesNotEfficient() as $table) { $errors[] = sprintf('Query plan analyzer: in efficient index use in table "%s"', $table); } } @@ -141,5 +136,4 @@ private function analyze(CallLike $callLike, Scope $scope): array return $ruleErrors; } - } diff --git a/tests/default/config/.phpstan-dba-mysqli.cache b/tests/default/config/.phpstan-dba-mysqli.cache index 52d40bd65..9f1fc4ef5 100644 --- a/tests/default/config/.phpstan-dba-mysqli.cache +++ b/tests/default/config/.phpstan-dba-mysqli.cache @@ -3,6 +3,72 @@ 'schemaHash' => NULL, 'records' => array ( + 'SELECT + adaid + FROM + ada' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 1, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + )), + ), + ), 'SELECT adaid FROM @@ -1525,6 +1591,70 @@ ), ), 'SELECT adaid +FROM ada' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 1, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + )), + ), + ), + 'SELECT adaid FROM ada' => array ( 'result' => @@ -2932,6 +3062,64 @@ FROM ada' => ), ), 'SELECT email +FROM ada' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 1, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\StringType::__set_state(array( + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\StringType::__set_state(array( + )), + )), + ), + ), + 'SELECT email FROM ada' => array ( 'result' => diff --git a/tests/default/config/.phpstan-dba-pdo-mysql.cache b/tests/default/config/.phpstan-dba-pdo-mysql.cache index 52d40bd65..9f1fc4ef5 100644 --- a/tests/default/config/.phpstan-dba-pdo-mysql.cache +++ b/tests/default/config/.phpstan-dba-pdo-mysql.cache @@ -3,6 +3,72 @@ 'schemaHash' => NULL, 'records' => array ( + 'SELECT + adaid + FROM + ada' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 1, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + )), + ), + ), 'SELECT adaid FROM @@ -1525,6 +1591,70 @@ ), ), 'SELECT adaid +FROM ada' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 1, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + )), + ), + ), + 'SELECT adaid FROM ada' => array ( 'result' => @@ -2932,6 +3062,64 @@ FROM ada' => ), ), 'SELECT email +FROM ada' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 1, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\StringType::__set_state(array( + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\StringType::__set_state(array( + )), + )), + ), + ), + 'SELECT email FROM ada' => array ( 'result' => diff --git a/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache b/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache index 4cd37aa1a..af60f78c4 100644 --- a/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache +++ b/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache @@ -3,6 +3,72 @@ 'schemaHash' => NULL, 'records' => array ( + 'SELECT + adaid + FROM + ada' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 1, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + )), + ), + ), 'SELECT adaid FROM @@ -1525,6 +1591,70 @@ ), ), 'SELECT adaid +FROM ada' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 1, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + )), + ), + ), + 'SELECT adaid FROM ada' => array ( 'result' => @@ -2932,6 +3062,64 @@ FROM ada' => ), ), 'SELECT email +FROM ada' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 1, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\StringType::__set_state(array( + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\StringType::__set_state(array( + )), + )), + ), + ), + 'SELECT email FROM ada' => array ( 'result' => diff --git a/tests/rules/QueryPlanAnalyzerRuleTest.php b/tests/rules/QueryPlanAnalyzerRuleTest.php index 6eb85e570..35b751060 100644 --- a/tests/rules/QueryPlanAnalyzerRuleTest.php +++ b/tests/rules/QueryPlanAnalyzerRuleTest.php @@ -4,7 +4,6 @@ use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; -use staabm\PHPStanDba\Rules\PdoStatementExecuteMethodRule; use staabm\PHPStanDba\Rules\QueryPlanAnalyzerRule; /** @@ -29,7 +28,7 @@ public function testParameterErrors(): void $this->analyse([__DIR__.'/data/query-plan-analyzer.php'], [ [ 'Query plan analyzer: table "ada" is not using an index', - 7, + 9, ], ]); } diff --git a/tests/rules/config/.phpstan-dba-mysqli.cache b/tests/rules/config/.phpstan-dba-mysqli.cache index 34ea981ce..d64dab1cb 100644 --- a/tests/rules/config/.phpstan-dba-mysqli.cache +++ b/tests/rules/config/.phpstan-dba-mysqli.cache @@ -39,6 +39,348 @@ 5 => NULL, ), ), + 'SELECT + ada.*, + COALESCE(NULLIF(email, ""), email) AS email + FROM ada + INNER JOIN ak ON (ak.adaid = ada.adaid AND ak.akid = \'1\') + WHERE adaid = 1 ORDER BY COALESCE(NULLIF(email, ""), email) ASC' => + array ( + 'result' => + array ( + 5 => NULL, + ), + ), + 'SELECT + ada.*, + COALESCE(NULLIF(email, ""), email) AS email + FROM ada + INNER JOIN ak ON (ak.adaid = ada.adaid AND ak.akid = :akid) + WHERE adaid = 1 ORDER BY COALESCE(NULLIF(email, ""), email) ASC' => + array ( + 'result' => + array ( + 5 => NULL, + ), + ), + 'SELECT + ada.*, + COALESCE(NULLIF(email, ""), email) AS email + FROM ada + INNER JOIN ak ON (ak.adaid = ada.adaid AND ak.akid = ?) + WHERE adaid = 1 ORDER BY COALESCE(NULLIF(email, ""), email) ASC' => + array ( + 'result' => + array ( + 5 => NULL, + ), + ), + 'SELECT * FROM `ada` WHERE adaid = 1' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), + 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), 'SELECT * FROM ada GROUP BY doesNotExist' => array ( 'result' => diff --git a/tests/rules/config/.phpstan-dba-pdo-mysql.cache b/tests/rules/config/.phpstan-dba-pdo-mysql.cache index 34ea981ce..d64dab1cb 100644 --- a/tests/rules/config/.phpstan-dba-pdo-mysql.cache +++ b/tests/rules/config/.phpstan-dba-pdo-mysql.cache @@ -39,6 +39,348 @@ 5 => NULL, ), ), + 'SELECT + ada.*, + COALESCE(NULLIF(email, ""), email) AS email + FROM ada + INNER JOIN ak ON (ak.adaid = ada.adaid AND ak.akid = \'1\') + WHERE adaid = 1 ORDER BY COALESCE(NULLIF(email, ""), email) ASC' => + array ( + 'result' => + array ( + 5 => NULL, + ), + ), + 'SELECT + ada.*, + COALESCE(NULLIF(email, ""), email) AS email + FROM ada + INNER JOIN ak ON (ak.adaid = ada.adaid AND ak.akid = :akid) + WHERE adaid = 1 ORDER BY COALESCE(NULLIF(email, ""), email) ASC' => + array ( + 'result' => + array ( + 5 => NULL, + ), + ), + 'SELECT + ada.*, + COALESCE(NULLIF(email, ""), email) AS email + FROM ada + INNER JOIN ak ON (ak.adaid = ada.adaid AND ak.akid = ?) + WHERE adaid = 1 ORDER BY COALESCE(NULLIF(email, ""), email) ASC' => + array ( + 'result' => + array ( + 5 => NULL, + ), + ), + 'SELECT * FROM `ada` WHERE adaid = 1' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), + 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), 'SELECT * FROM ada GROUP BY doesNotExist' => array ( 'result' => diff --git a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache index 18a26a62a..d379274ee 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache @@ -75,6 +75,159 @@ 5 => NULL, ), ), + 'SELECT * FROM `ada` WHERE adaid = 1' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => array ( 'result' => @@ -235,6 +388,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'group statement\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -243,6 +400,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -251,6 +412,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM unknown_table' => array ( @@ -259,6 +424,10 @@ 'message' => 'Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => 1146, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT adaid FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -365,6 +534,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'field list\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email FROM ada WHERE adaid IN (\'1\')' => array ( @@ -410,6 +583,11 @@ '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', 'code' => 1064, )), + 'result' => + array ( + 5 => NULL, + 3 => NULL, + ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -418,6 +596,10 @@ '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', 'code' => 1064, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada @@ -594,6 +776,10 @@ 'message' => 'Unknown column \'xy\' in \'group statement\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada WHERE adaid = \'1\'' => array ( @@ -736,6 +922,7 @@ ), 'SELECT email, adaid FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -842,6 +1029,10 @@ '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, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( @@ -852,6 +1043,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada' => array ( + 'error' => NULL, 'result' => array ( 3 => @@ -1112,6 +1304,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -1265,6 +1458,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -1605,6 +1799,11 @@ 'message' => 'Unknown column \'asdsa\' in \'where clause\'', 'code' => 1054, )), + 'result' => + array ( + 3 => NULL, + 5 => NULL, + ), ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE gesperrt=\'1\'' => array ( diff --git a/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache b/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache index 8cc8f1bf0..310cab4f0 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache @@ -39,6 +39,348 @@ 5 => NULL, ), ), + 'SELECT + ada.*, + COALESCE(NULLIF(email, ""), email) AS email + FROM ada + INNER JOIN ak ON (ak.adaid = ada.adaid AND ak.akid = \'1\') + WHERE adaid = 1 ORDER BY COALESCE(NULLIF(email, ""), email) ASC' => + array ( + 'result' => + array ( + 5 => NULL, + ), + ), + 'SELECT + ada.*, + COALESCE(NULLIF(email, ""), email) AS email + FROM ada + INNER JOIN ak ON (ak.adaid = ada.adaid AND ak.akid = :akid) + WHERE adaid = 1 ORDER BY COALESCE(NULLIF(email, ""), email) ASC' => + array ( + 'result' => + array ( + 5 => NULL, + ), + ), + 'SELECT + ada.*, + COALESCE(NULLIF(email, ""), email) AS email + FROM ada + INNER JOIN ak ON (ak.adaid = ada.adaid AND ak.akid = ?) + WHERE adaid = 1 ORDER BY COALESCE(NULLIF(email, ""), email) ASC' => + array ( + 'result' => + array ( + 5 => NULL, + ), + ), + 'SELECT * FROM `ada` WHERE adaid = 1' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), + 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), 'SELECT * FROM ada GROUP BY doesNotExist' => array ( 'error' => @@ -46,10 +388,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'group statement\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -58,10 +396,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'order clause\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -70,10 +404,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'where clause\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM unknown_table' => array ( @@ -82,10 +412,6 @@ 'message' => 'SQLSTATE[42S02]: Base table or view not found: 1146 Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => '42S02', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT adaid FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -192,10 +518,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'field list\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email FROM ada WHERE adaid IN (\'1\')' => array ( @@ -223,6 +545,17 @@ 'code' => '42000', )), ), + 'SELECT email adaid + WHERE gesperrt = \'1\' AND email LIKE \'%@example.com\' + FROM ada + LIMIT 1' => + array ( + 'error' => + staabm\PHPStanDba\Error::__set_state(array( + 'message' => '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 \'FROM ada LIMIT 0\' at line 3', + 'code' => '42000', + )), + ), 'SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada' => array ( 'error' => @@ -230,11 +563,6 @@ 'message' => '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', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - 3 => NULL, - ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -243,10 +571,90 @@ 'message' => '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 \'gesperrt freigabe1u1 FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' + FOR UPDATE' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' + LIMIT \'1\'' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' + LIMIT \'1\' + FOR UPDATE' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' + LIMIT \'1\' + OFFSET \'1\'' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' + LIMIT \'1\' + OFFSET \'1\' + FOR SHARE' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' + LIMIT \'1\' + OFFSET \'1\' + FOR UPDATE' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' + LIMIT \'1\' + OFFSET 1' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' + LIMIT \'1\', \'1\'' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' + LIMIT \'1\', \'1\'' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' AND email LIKE \'%@example%\' + LIMIT 1' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid + FROM ada + WHERE gesperrt = \'1\' AND email LIKE NULL + LIMIT 1' => + array ( + 'error' => NULL, ), 'SELECT email, adaid FROM ada @@ -339,10 +747,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'xy\' in \'group statement\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada WHERE adaid = \'1\'' => array ( @@ -485,7 +889,6 @@ ), 'SELECT email, adaid FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -592,10 +995,6 @@ 'message' => '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 \'FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( @@ -606,7 +1005,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada' => array ( - 'error' => NULL, 'result' => array ( 3 => @@ -860,9 +1258,13 @@ array ( 'error' => NULL, ), - 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada LIMIT 1' => + 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada + WHERE (gesperrt=\'1\' AND freigabe1u1=1) OR (gesperrt=\'1\' AND freigabe1u1=0)' => array ( 'error' => NULL, + ), + 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada LIMIT 1' => + array ( 'result' => array ( 5 => @@ -1016,7 +1418,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -1357,11 +1758,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'asdsa\' in \'where clause\'', 'code' => '42S22', )), - 'result' => - array ( - 3 => NULL, - 5 => NULL, - ), ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE gesperrt=\'1\'' => array ( diff --git a/tests/rules/data/query-plan-analyzer.php b/tests/rules/data/query-plan-analyzer.php index d9f00afaa..f2527e3e2 100644 --- a/tests/rules/data/query-plan-analyzer.php +++ b/tests/rules/data/query-plan-analyzer.php @@ -2,8 +2,15 @@ namespace QueryPlanAnalyzerTest; +use PDO; + class Foo { - public function doFoo(\PDO $pdo) { + public function noindex(PDO $pdo, int $adaid):void + { $pdo->query("SELECT * FROM `ada` WHERE email = 'test@example.com';"); } + + public function indexed(PDO $pdo, int $adaid):void { + $pdo->query("SELECT * FROM `ada` WHERE adaid = ". $adaid); + } } From 56f7136363ab16e6448c3c44d82c80369ed0a1a0 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Mon, 23 May 2022 17:48:24 +0200 Subject: [PATCH 07/24] Update QueryReflection.php --- src/QueryReflection/QueryReflection.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/QueryReflection/QueryReflection.php b/src/QueryReflection/QueryReflection.php index c5f7c4783..d694a12d1 100644 --- a/src/QueryReflection/QueryReflection.php +++ b/src/QueryReflection/QueryReflection.php @@ -420,6 +420,10 @@ public function analyzeQueryPlan(Scope $scope, Expr $queryExpr, ?Type $parameter if (!$reflector instanceof RecordingReflector) { throw new DbaException('Query plan analysis is only supported with a recording reflector'); } + // TODO + if ($reflector instanceof PdoPgSqlQueryReflector) { + throw new DbaException('Query plan analysis is not yet supported with the pdo-pgsql reflector'); + } $ds = $reflector->getDatasource(); if (null === $ds) { From bf7eefcd6dc9355c328a000b3f9f154f97ac5f43 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Mon, 23 May 2022 19:01:16 +0200 Subject: [PATCH 08/24] progress --- README.md | 3 ++ config/dba.neon | 20 ++++++++++- docs/mysql.md | 1 + docs/query-plan-analysis.md | 29 +++++++++++++++ docs/record-and-replay.md | 1 + src/Analyzer/QueryPlanAnalyzerMysql.php | 20 +++++++++-- src/QueryReflection/QueryReflection.php | 3 +- src/QueryReflection/RuntimeConfiguration.php | 38 ++++++++++++++++++++ src/Rules/QueryPlanAnalyzerRule.php | 4 +++ tests/rules/QueryPlanAnalyzerRuleTest.php | 19 ++++++++-- tests/rules/config/query-plan-analyzer.neon | 12 ------- tests/rules/data/query-plan-analyzer.php | 16 ++++++--- 12 files changed, 143 insertions(+), 23 deletions(-) create mode 100644 docs/query-plan-analysis.md delete mode 100644 tests/rules/config/query-plan-analyzer.neon diff --git a/README.md b/README.md index 74c8c514e..285a03691 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ This extension provides the following features: * result set type-inferrence * inspect sql queries, detect errors and placeholder/bound value mismatches +* query plan analysis to detect performance issues * builtin support for `doctrine/dbal`, `mysqli`, and `PDO` * API to configure the same features for your custom sql based database access layer @@ -49,6 +50,7 @@ $cacheFile = __DIR__.'/.phpstan-dba.cache'; $config = new RuntimeConfiguration(); // $config->debugMode(true); // $config->stringifyTypes(true); +// $config->analyzeQueryPlans(true); // TODO: Put your database credentials here $mysqli = new mysqli('hostname', 'username', 'password', 'database'); @@ -97,6 +99,7 @@ includes: - [Runtime configuration](https://github.com/staabm/phpstan-dba/blob/main/docs/configuration.md) - [Record and Replay](https://github.com/staabm/phpstan-dba/blob/main/docs/record-and-replay.md) +- [Query Plan Analysis](https://github.com/staabm/phpstan-dba/blob/main/docs/query-plan-analysis.md) - [Custom Query APIs Support](https://github.com/staabm/phpstan-dba/blob/main/docs/rules.md) - [MySQL Support](https://github.com/staabm/phpstan-dba/blob/main/docs/mysql.md) - [PGSQL Support](https://github.com/staabm/phpstan-dba/blob/main/docs/pgsql.md) diff --git a/config/dba.neon b/config/dba.neon index cbf4faa3b..7e2b6268c 100644 --- a/config/dba.neon +++ b/config/dba.neon @@ -62,9 +62,27 @@ services: tags: [phpstan.rules.rule] arguments: classMethods: + # prepared statement methods + - 'Doctrine\DBAL\Connection::executeQuery#0' + - 'Doctrine\DBAL\Connection::executeCacheQuery#0' + - 'Doctrine\DBAL\Connection::executeStatement#0' + - 'Doctrine\DBAL\Connection::fetchAssociative#0' + - 'Doctrine\DBAL\Connection::fetchNumeric#0' + - 'Doctrine\DBAL\Connection::fetchOne#0' + - 'Doctrine\DBAL\Connection::fetchAllNumeric#0' + - 'Doctrine\DBAL\Connection::fetchAllAssociative#0' + - 'Doctrine\DBAL\Connection::fetchAllKeyValue#0' + - 'Doctrine\DBAL\Connection::fetchAllAssociativeIndexed#0' + - 'Doctrine\DBAL\Connection::fetchFirstColumn#0' + - 'Doctrine\DBAL\Connection::iterateNumeric#0' + - 'Doctrine\DBAL\Connection::iterateAssociative#0' + - 'Doctrine\DBAL\Connection::iterateKeyValue#0' + - 'Doctrine\DBAL\Connection::iterateAssociativeIndexed#0' + - 'Doctrine\DBAL\Connection::iterateColumn#0' + - 'Doctrine\DBAL\Connection::executeUpdate#0' # deprecated in doctrine + # regular statements - 'PDO::query#0' - 'PDO::prepare#0' - 'mysqli::query#0' - 'Doctrine\DBAL\Connection::query#0' # deprecated in doctrine - 'Doctrine\DBAL\Connection::exec#0' # deprecated in doctrine - # TODO diff --git a/docs/mysql.md b/docs/mysql.md index d0dffe000..d93b7ee38 100644 --- a/docs/mysql.md +++ b/docs/mysql.md @@ -24,6 +24,7 @@ $cacheFile = __DIR__.'/.phpstan-dba.cache'; $config = new RuntimeConfiguration(); // $config->debugMode(true); // $config->stringifyTypes(true); +// $config->analyzeQueryPlans(true); // TODO: Put your database credentials here $mysqli = new mysqli('hostname', 'username', 'password', 'database'); diff --git a/docs/query-plan-analysis.md b/docs/query-plan-analysis.md new file mode 100644 index 000000000..c0819f623 --- /dev/null +++ b/docs/query-plan-analysis.md @@ -0,0 +1,29 @@ +# Query Plan Analysis + +Within your `phpstan-dba-bootstrap.php` file, you can optionally enable query plan analysis. +When enabled, `phpstandba` will error when queries are not using indices or queries are inefficient. + +Passing `true` will enable the feature: + +```php +$config = new RuntimeConfiguration(); +$config->analyzeQueryPlans(true); +``` + +For more fine grained control, you can pass a positive-integer describing the number of unindexed reads a query is allowed to execute before being considered inefficient. + +```php +$config = new RuntimeConfiguration(); +$config->analyzeQueryPlans(100000); +``` + +To disable the effiency analysis but just check for queries not using indexes at all, pass `0`. + +```php +$config = new RuntimeConfiguration(); +$config->analyzeQueryPlans(0); +``` + +**Note:** "Query Plan Analysis" requires an active database connection. + +**Note:** ["Query Plan Analysis" is not yet supported on the PGSQL driver](https://github.com/staabm/phpstan-dba/issues/378) diff --git a/docs/record-and-replay.md b/docs/record-and-replay.md index b45edf42e..685ed8e4a 100644 --- a/docs/record-and-replay.md +++ b/docs/record-and-replay.md @@ -23,6 +23,7 @@ $cacheFile = __DIR__.'/.phpstan-dba.cache'; $config = new RuntimeConfiguration(); // $config->debugMode(true); // $config->stringifyTypes(true); +// $config->analyzeQueryPlans(true); QueryReflection::setupReflector( new ReplayQueryReflector( diff --git a/src/Analyzer/QueryPlanAnalyzerMysql.php b/src/Analyzer/QueryPlanAnalyzerMysql.php index 547533191..a99ca826f 100644 --- a/src/Analyzer/QueryPlanAnalyzerMysql.php +++ b/src/Analyzer/QueryPlanAnalyzerMysql.php @@ -7,9 +7,15 @@ use mysqli; use PDO; use PHPStan\ShouldNotHappenException; +use staabm\PHPStanDba\QueryReflection\QueryReflection; final class QueryPlanAnalyzerMysql { + /** + * number of unindexed reads allowed before a queries is considered inefficient. + */ + public const DEFAULT_UNINDEXED_READS_THRESHOLD = 100000; + /** * @var PDO|mysqli */ @@ -48,6 +54,11 @@ public function analyze(string $query): QueryPlanResult private function buildResult(\IteratorAggregate $it): QueryPlanResult { $result = new QueryPlanResult(); + $allowedUnindexedReads = QueryReflection::getRuntimeConfiguration()->getNumberOfAllowedUnindexedReads(); + + if (false === $allowedUnindexedReads) { + throw new ShouldNotHappenException(); + } foreach ($it as $row) { // we cannot analyse tables without rows -> mysql will just return 'no matching row in const table' @@ -57,8 +68,13 @@ private function buildResult(\IteratorAggregate $it): QueryPlanResult if (null === $row['key']) { $result->addRow($row['table'], QueryPlanResult::NO_INDEX); - } elseif ($row['rows'] > 100000) { // XXX add RuntimeConfiguration - $result->addRow($row['table'], QueryPlanResult::NOT_EFFICIENT); + } else { + if (true === $allowedUnindexedReads && $row['rows'] > self::DEFAULT_UNINDEXED_READS_THRESHOLD) { + $result->addRow($row['table'], QueryPlanResult::NOT_EFFICIENT); + } + if (\is_int($allowedUnindexedReads) && $row['rows'] > $allowedUnindexedReads) { + $result->addRow($row['table'], QueryPlanResult::NOT_EFFICIENT); + } } } diff --git a/src/QueryReflection/QueryReflection.php b/src/QueryReflection/QueryReflection.php index d694a12d1..d737c626e 100644 --- a/src/QueryReflection/QueryReflection.php +++ b/src/QueryReflection/QueryReflection.php @@ -420,9 +420,8 @@ public function analyzeQueryPlan(Scope $scope, Expr $queryExpr, ?Type $parameter if (!$reflector instanceof RecordingReflector) { throw new DbaException('Query plan analysis is only supported with a recording reflector'); } - // TODO if ($reflector instanceof PdoPgSqlQueryReflector) { - throw new DbaException('Query plan analysis is not yet supported with the pdo-pgsql reflector'); + throw new DbaException('Query plan analysis is not yet supported with the pdo-pgsql reflector, see https://github.com/staabm/phpstan-dba/issues/378'); } $ds = $reflector->getDatasource(); diff --git a/src/QueryReflection/RuntimeConfiguration.php b/src/QueryReflection/RuntimeConfiguration.php index cacacaf65..16cacb679 100644 --- a/src/QueryReflection/RuntimeConfiguration.php +++ b/src/QueryReflection/RuntimeConfiguration.php @@ -5,6 +5,7 @@ namespace staabm\PHPStanDba\QueryReflection; use PHPStan\Php\PhpVersion; +use staabm\PHPStanDba\Analyzer\QueryPlanAnalyzerMysql; final class RuntimeConfiguration { @@ -39,6 +40,10 @@ final class RuntimeConfiguration * @var bool */ private $stringifyTypes = false; + /** + * @var bool|0|positive-int + */ + private $numberOfAllowedUnindexedReads = false; public static function create(): self { @@ -70,6 +75,13 @@ public function defaultFetchMode(int $mode): self return $this; } + /** + * When enabled, a DbaException will be thrown in case a sql query cannot be analyzed. + * + * Otherwise these queries will be ignored. + * + * @return $this + */ public function debugMode(bool $mode): self { $this->debugMode = $mode; @@ -88,6 +100,32 @@ public function stringifyTypes(bool $stringify): self return $this; } + /** + * Enables query plan analysis, which indicates performance problems. + * + * Requires a active database connection. + * + * @param bool|0|positive-int $numberOfAllowedUnindexedReads `true` to enable analysis. `false` to disable analysis. + * Otherwise the number of reads a query is allowed to execute, before it is considered inefficient, see QueryPlanAnalyzerMysql::DEFAULT_UNINDEXED_READS_THRESHOLD. + * `0` disables the efficiency checks but still scans for queries not using an index. + * + * @return $this + */ + public function analyzeQueryPlans($numberOfAllowedUnindexedReads = true): self + { + $this->numberOfAllowedUnindexedReads = $numberOfAllowedUnindexedReads; + + return $this; + } + + /** + * @return bool|0|positive-int + */ + public function getNumberOfAllowedUnindexedReads() + { + return $this->numberOfAllowedUnindexedReads; + } + public function isDebugEnabled(): bool { return $this->debugMode; diff --git a/src/Rules/QueryPlanAnalyzerRule.php b/src/Rules/QueryPlanAnalyzerRule.php index 08398388f..061e94b69 100644 --- a/src/Rules/QueryPlanAnalyzerRule.php +++ b/src/Rules/QueryPlanAnalyzerRule.php @@ -103,6 +103,10 @@ private function analyze(CallLike $callLike, Scope $scope): array return []; } + if (false === QueryReflection::getRuntimeConfiguration()->getNumberOfAllowedUnindexedReads()) { + return []; + } + $queryExpr = $args[0]->value; if ($scope->getType($queryExpr) instanceof MixedType) { diff --git a/tests/rules/QueryPlanAnalyzerRuleTest.php b/tests/rules/QueryPlanAnalyzerRuleTest.php index 35b751060..e1bbd42b2 100644 --- a/tests/rules/QueryPlanAnalyzerRuleTest.php +++ b/tests/rules/QueryPlanAnalyzerRuleTest.php @@ -4,6 +4,7 @@ use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; +use staabm\PHPStanDba\QueryReflection\QueryReflection; use staabm\PHPStanDba\Rules\QueryPlanAnalyzerRule; /** @@ -11,6 +12,16 @@ */ class QueryPlanAnalyzerRuleTest extends RuleTestCase { + protected function setUp(): void + { + QueryReflection::getRuntimeConfiguration()->analyzeQueryPlans(true); + } + + protected function tearDown(): void + { + QueryReflection::getRuntimeConfiguration()->analyzeQueryPlans(false); + } + protected function getRule(): Rule { return self::getContainer()->getByType(QueryPlanAnalyzerRule::class); @@ -19,7 +30,7 @@ protected function getRule(): Rule public static function getAdditionalConfigFiles(): array { return [ - __DIR__.'/config/query-plan-analyzer.neon', + __DIR__.'/../../config/dba.neon', ]; } @@ -28,7 +39,11 @@ public function testParameterErrors(): void $this->analyse([__DIR__.'/data/query-plan-analyzer.php'], [ [ 'Query plan analyzer: table "ada" is not using an index', - 9, + 12, + ], + [ + 'Query plan analyzer: table "ada" is not using an index', + 17, ], ]); } diff --git a/tests/rules/config/query-plan-analyzer.neon b/tests/rules/config/query-plan-analyzer.neon deleted file mode 100644 index 257c88070..000000000 --- a/tests/rules/config/query-plan-analyzer.neon +++ /dev/null @@ -1,12 +0,0 @@ -includes: - - ../../../config/stubFiles.neon - - ../../../config/extensions.neon - -services: - - - class: staabm\PHPStanDba\Rules\QueryPlanAnalyzerRule - tags: [phpstan.rules.rule] - arguments: - classMethods: - - 'PDO::query#0' - - 'PDO::prepare#0' diff --git a/tests/rules/data/query-plan-analyzer.php b/tests/rules/data/query-plan-analyzer.php index f2527e3e2..188c1164f 100644 --- a/tests/rules/data/query-plan-analyzer.php +++ b/tests/rules/data/query-plan-analyzer.php @@ -2,15 +2,23 @@ namespace QueryPlanAnalyzerTest; +use Doctrine\DBAL\Connection; use PDO; -class Foo { - public function noindex(PDO $pdo, int $adaid):void +class Foo +{ + public function noindex(PDO $pdo, int $adaid): void { $pdo->query("SELECT * FROM `ada` WHERE email = 'test@example.com';"); } - public function indexed(PDO $pdo, int $adaid):void { - $pdo->query("SELECT * FROM `ada` WHERE adaid = ". $adaid); + public function noindexDbal(Connection $conn, int $adaid): void + { + $conn->executeQuery("SELECT * FROM `ada` WHERE email = 'test@example.com';"); + } + + public function indexed(PDO $pdo, int $adaid): void + { + $pdo->query('SELECT * FROM `ada` WHERE adaid = '.$adaid); } } From c357e48c987c8ad36caba0137ed01f83e445a8be Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Mon, 23 May 2022 19:02:19 +0200 Subject: [PATCH 09/24] fix --- docs/query-plan-analysis.md | 2 +- src/Analyzer/QueryPlanAnalyzerMysql.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/query-plan-analysis.md b/docs/query-plan-analysis.md index c0819f623..0ee26cd4e 100644 --- a/docs/query-plan-analysis.md +++ b/docs/query-plan-analysis.md @@ -17,7 +17,7 @@ $config = new RuntimeConfiguration(); $config->analyzeQueryPlans(100000); ``` -To disable the effiency analysis but just check for queries not using indexes at all, pass `0`. +To disable the effiency analysis but just check for queries not using indices at all, pass `0`. ```php $config = new RuntimeConfiguration(); diff --git a/src/Analyzer/QueryPlanAnalyzerMysql.php b/src/Analyzer/QueryPlanAnalyzerMysql.php index a99ca826f..f149f3e9c 100644 --- a/src/Analyzer/QueryPlanAnalyzerMysql.php +++ b/src/Analyzer/QueryPlanAnalyzerMysql.php @@ -12,7 +12,7 @@ final class QueryPlanAnalyzerMysql { /** - * number of unindexed reads allowed before a queries is considered inefficient. + * number of unindexed reads allowed before a query is considered inefficient. */ public const DEFAULT_UNINDEXED_READS_THRESHOLD = 100000; From d607ad54a289574a11573303d7137ab8a2908835 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Mon, 23 May 2022 19:13:08 +0200 Subject: [PATCH 10/24] fix --- src/Rules/QueryPlanAnalyzerRule.php | 2 +- tests/rules/QueryPlanAnalyzerRuleTest.php | 14 ++++-- .../config/.phpunit-phpstan-dba-mysqli.cache | 46 ------------------- .../.phpunit-phpstan-dba-pdo-mysql.cache | 46 +++++++++++++++++++ 4 files changed, 56 insertions(+), 52 deletions(-) diff --git a/src/Rules/QueryPlanAnalyzerRule.php b/src/Rules/QueryPlanAnalyzerRule.php index 061e94b69..eeded095c 100644 --- a/src/Rules/QueryPlanAnalyzerRule.php +++ b/src/Rules/QueryPlanAnalyzerRule.php @@ -128,7 +128,7 @@ private function analyze(CallLike $callLike, Scope $scope): array } } else { foreach ($queryPlanResult->getTablesNotEfficient() as $table) { - $errors[] = sprintf('Query plan analyzer: in efficient index use in table "%s"', $table); + $errors[] = sprintf('Query plan analyzer: inefficient index use in table "%s"', $table); } } } diff --git a/tests/rules/QueryPlanAnalyzerRuleTest.php b/tests/rules/QueryPlanAnalyzerRuleTest.php index e1bbd42b2..6662131dc 100644 --- a/tests/rules/QueryPlanAnalyzerRuleTest.php +++ b/tests/rules/QueryPlanAnalyzerRuleTest.php @@ -12,10 +12,10 @@ */ class QueryPlanAnalyzerRuleTest extends RuleTestCase { - protected function setUp(): void - { - QueryReflection::getRuntimeConfiguration()->analyzeQueryPlans(true); - } + /** + * @var bool|0|positive-int + */ + private $numberOfAllowedUnindexedReads; protected function tearDown(): void { @@ -24,6 +24,8 @@ protected function tearDown(): void protected function getRule(): Rule { + QueryReflection::getRuntimeConfiguration()->analyzeQueryPlans($this->numberOfAllowedUnindexedReads); + return self::getContainer()->getByType(QueryPlanAnalyzerRule::class); } @@ -34,8 +36,10 @@ public static function getAdditionalConfigFiles(): array ]; } - public function testParameterErrors(): void + public function testNotUsingIndex(): void { + $this->numberOfAllowedUnindexedReads = true; + $this->analyse([__DIR__.'/data/query-plan-analyzer.php'], [ [ 'Query plan analyzer: table "ada" is not using an index', diff --git a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache index d379274ee..5e955fe64 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache @@ -388,10 +388,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'group statement\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -400,10 +396,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -412,10 +404,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM unknown_table' => array ( @@ -424,10 +412,6 @@ 'message' => 'Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => 1146, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT adaid FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -534,10 +518,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'field list\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email FROM ada WHERE adaid IN (\'1\')' => array ( @@ -583,11 +563,6 @@ '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', 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - 3 => NULL, - ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -596,10 +571,6 @@ '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', 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada @@ -776,10 +747,6 @@ 'message' => 'Unknown column \'xy\' in \'group statement\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada WHERE adaid = \'1\'' => array ( @@ -922,7 +889,6 @@ ), 'SELECT email, adaid FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -1029,10 +995,6 @@ '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, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( @@ -1043,7 +1005,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada' => array ( - 'error' => NULL, 'result' => array ( 3 => @@ -1304,7 +1265,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -1458,7 +1418,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -1799,11 +1758,6 @@ 'message' => 'Unknown column \'asdsa\' in \'where clause\'', 'code' => 1054, )), - 'result' => - array ( - 3 => NULL, - 5 => NULL, - ), ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE gesperrt=\'1\'' => array ( diff --git a/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache b/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache index 310cab4f0..479972b71 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache @@ -388,6 +388,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'group statement\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -396,6 +400,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'order clause\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -404,6 +412,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'where clause\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM unknown_table' => array ( @@ -412,6 +424,10 @@ 'message' => 'SQLSTATE[42S02]: Base table or view not found: 1146 Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => '42S02', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT adaid FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -518,6 +534,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'field list\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email FROM ada WHERE adaid IN (\'1\')' => array ( @@ -563,6 +583,11 @@ 'message' => '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', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + 3 => NULL, + ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -571,6 +596,10 @@ 'message' => '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 \'gesperrt freigabe1u1 FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada @@ -747,6 +776,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'xy\' in \'group statement\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada WHERE adaid = \'1\'' => array ( @@ -889,6 +922,7 @@ ), 'SELECT email, adaid FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -995,6 +1029,10 @@ 'message' => '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 \'FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( @@ -1005,6 +1043,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada' => array ( + 'error' => NULL, 'result' => array ( 3 => @@ -1265,6 +1304,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -1418,6 +1458,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -1758,6 +1799,11 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'asdsa\' in \'where clause\'', 'code' => '42S22', )), + 'result' => + array ( + 3 => NULL, + 5 => NULL, + ), ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE gesperrt=\'1\'' => array ( From 1701dca8f67a4e009338dbd5f8c1e545b6652696 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Mon, 23 May 2022 19:30:05 +0200 Subject: [PATCH 11/24] progress --- docs/query-plan-analysis.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/query-plan-analysis.md b/docs/query-plan-analysis.md index 0ee26cd4e..c398207c4 100644 --- a/docs/query-plan-analysis.md +++ b/docs/query-plan-analysis.md @@ -1,7 +1,7 @@ # Query Plan Analysis Within your `phpstan-dba-bootstrap.php` file, you can optionally enable query plan analysis. -When enabled, `phpstandba` will error when queries are not using indices or queries are inefficient. +When enabled, `phpstan-dba` will error when queries are not using indices or queries are inefficient. Passing `true` will enable the feature: @@ -11,6 +11,7 @@ $config->analyzeQueryPlans(true); ``` For more fine grained control, you can pass a positive-integer describing the number of unindexed reads a query is allowed to execute before being considered inefficient. +This will only affect queries which already use an index. ```php $config = new RuntimeConfiguration(); From bf9e3c34caf04793dc9629d83acba16cbe923b57 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Mon, 23 May 2022 20:54:08 +0200 Subject: [PATCH 12/24] Update query-plan-analysis.md --- docs/query-plan-analysis.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/query-plan-analysis.md b/docs/query-plan-analysis.md index c398207c4..a8ba343de 100644 --- a/docs/query-plan-analysis.md +++ b/docs/query-plan-analysis.md @@ -25,6 +25,8 @@ $config = new RuntimeConfiguration(); $config->analyzeQueryPlans(0); ``` +**Note:** For a meaningful performance analysis it is vital to utilize a database, which containts data and schema as similar as possible to the production database. + **Note:** "Query Plan Analysis" requires an active database connection. **Note:** ["Query Plan Analysis" is not yet supported on the PGSQL driver](https://github.com/staabm/phpstan-dba/issues/378) From 66cd3966fec5fec30ce1137d6503bd1f02ee997b Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 24 May 2022 22:03:11 +0200 Subject: [PATCH 13/24] progress --- src/QueryReflection/QueryReflection.php | 5 +++++ tests/rules/QueryPlanAnalyzerRuleTest.php | 4 ++++ tests/rules/data/query-plan-analyzer.php | 16 +++++++++++++--- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/QueryReflection/QueryReflection.php b/src/QueryReflection/QueryReflection.php index d737c626e..71b416e41 100644 --- a/src/QueryReflection/QueryReflection.php +++ b/src/QueryReflection/QueryReflection.php @@ -435,6 +435,11 @@ public function analyzeQueryPlan(Scope $scope, Expr $queryExpr, ?Type $parameter if ('' === $queryString) { continue; } + + if ($reflector->validateQueryString($queryString) instanceof Error) { + continue; + } + yield $queryPlanAnalyzer->analyze($queryString); } } diff --git a/tests/rules/QueryPlanAnalyzerRuleTest.php b/tests/rules/QueryPlanAnalyzerRuleTest.php index 6662131dc..5f5bf1a87 100644 --- a/tests/rules/QueryPlanAnalyzerRuleTest.php +++ b/tests/rules/QueryPlanAnalyzerRuleTest.php @@ -49,6 +49,10 @@ public function testNotUsingIndex(): void 'Query plan analyzer: table "ada" is not using an index', 17, ], + [ + 'Query plan analyzer: table "ada" is not using an index', + 22, + ], ]); } } diff --git a/tests/rules/data/query-plan-analyzer.php b/tests/rules/data/query-plan-analyzer.php index 188c1164f..7adfac491 100644 --- a/tests/rules/data/query-plan-analyzer.php +++ b/tests/rules/data/query-plan-analyzer.php @@ -7,14 +7,24 @@ class Foo { - public function noindex(PDO $pdo, int $adaid): void + public function noindex(PDO $pdo): void { $pdo->query("SELECT * FROM `ada` WHERE email = 'test@example.com';"); } - public function noindexDbal(Connection $conn, int $adaid): void + public function noindexDbal(Connection $conn): void { - $conn->executeQuery("SELECT * FROM `ada` WHERE email = 'test@example.com';"); + $conn->executeQuery("SELECT *,adaid FROM `ada` WHERE email = 'test@example.com';"); + } + + public function noindexPreparedDbal(Connection $conn, string $email): void + { + $conn->executeQuery("SELECT * FROM ada WHERE email = ?", [$email]); + } + + public function syntaxError(Connection $conn): void + { + $conn->executeQuery("SELECT FROM WHERE"); } public function indexed(PDO $pdo, int $adaid): void From 6632980c264f92d7243897be05e30a533a2d0aa2 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 24 May 2022 22:04:52 +0200 Subject: [PATCH 14/24] record --- .phpstan-dba-mysqli.cache | 8 + .phpstan-dba-pdo-mysql.cache | 146 ---- src/Analyzer/QueryPlanAnalyzerMysql.php | 1 + .../default/config/.phpstan-dba-mysqli.cache | 4 - .../config/.phpstan-dba-pdo-mysql.cache | 4 - .../.phpunit-phpstan-dba-pdo-mysql.cache | 4 - tests/rules/config/.phpstan-dba-mysqli.cache | 671 +++++++++++++- .../rules/config/.phpstan-dba-pdo-mysql.cache | 671 +++++++++++++- .../config/.phpunit-phpstan-dba-mysqli.cache | 823 +++++++++++++++++- .../.phpunit-phpstan-dba-pdo-mysql.cache | 691 ++++++++++++++- tests/rules/data/query-plan-analyzer.php | 4 +- 11 files changed, 2734 insertions(+), 293 deletions(-) diff --git a/.phpstan-dba-mysqli.cache b/.phpstan-dba-mysqli.cache index 6c9604223..ebe33e71a 100644 --- a/.phpstan-dba-mysqli.cache +++ b/.phpstan-dba-mysqli.cache @@ -661,6 +661,14 @@ )), ), ), + 'SELECT * FROM `ada` WHERE adaid = 1' => + array ( + 'error' => NULL, + ), + 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => + array ( + 'error' => NULL, + ), 'SELECT adaid FROM ada LIMIT 1 FOR SHARE' => array ( 'error' => NULL, diff --git a/.phpstan-dba-pdo-mysql.cache b/.phpstan-dba-pdo-mysql.cache index de678863b..c5544ecca 100644 --- a/.phpstan-dba-pdo-mysql.cache +++ b/.phpstan-dba-pdo-mysql.cache @@ -946,152 +946,6 @@ WHERE table_name = \'1970-01-01\'' => ), 'SELECT column_name, column_default, is_nullable FROM information_schema.columns -WHERE table_name = ?' => - array ( - 'result' => - array ( - 5 => NULL, - ), - ), - 'SELECT column_name, column_default, is_nullable -FROM information_schema.columns -WHERE table_name = \'1970-01-01\'' => - array ( - 'result' => - array ( - 5 => - PHPStan\Type\Constant\ConstantArrayType::__set_state(array( - 'allArrays' => NULL, - 'nextAutoIndexes' => - array ( - 0 => 3, - ), - 'keyTypes' => - array ( - 0 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'COLUMN_NAME', - 'isClassString' => false, - )), - 1 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 0, - )), - 2 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'COLUMN_DEFAULT', - 'isClassString' => false, - )), - 3 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 1, - )), - 4 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'IS_NULLABLE', - 'isClassString' => false, - )), - 5 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 2, - )), - ), - 'valueTypes' => - array ( - 0 => - PHPStan\Type\StringType::__set_state(array( - )), - 1 => - PHPStan\Type\StringType::__set_state(array( - )), - 2 => - PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => false, - 'types' => - array ( - 0 => - PHPStan\Type\StringType::__set_state(array( - )), - 1 => - PHPStan\Type\NullType::__set_state(array( - )), - ), - )), - 3 => - PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => false, - 'types' => - array ( - 0 => - PHPStan\Type\StringType::__set_state(array( - )), - 1 => - PHPStan\Type\NullType::__set_state(array( - )), - ), - )), - 4 => - PHPStan\Type\StringType::__set_state(array( - )), - 5 => - PHPStan\Type\StringType::__set_state(array( - )), - ), - 'optionalKeys' => - array ( - ), - 'keyType' => - PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => true, - 'types' => - array ( - 0 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 0, - )), - 1 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 1, - )), - 2 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 2, - )), - 3 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'COLUMN_DEFAULT', - 'isClassString' => false, - )), - 4 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'COLUMN_NAME', - 'isClassString' => false, - )), - 5 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'IS_NULLABLE', - 'isClassString' => false, - )), - ), - )), - 'itemType' => - PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => false, - 'types' => - array ( - 0 => - PHPStan\Type\StringType::__set_state(array( - )), - 1 => - PHPStan\Type\NullType::__set_state(array( - )), - ), - )), - )), - ), - ), - 'SELECT column_name, column_default, is_nullable -FROM information_schema.columns WHERE table_name = ?' => array ( 'result' => diff --git a/src/Analyzer/QueryPlanAnalyzerMysql.php b/src/Analyzer/QueryPlanAnalyzerMysql.php index f149f3e9c..4989bc41f 100644 --- a/src/Analyzer/QueryPlanAnalyzerMysql.php +++ b/src/Analyzer/QueryPlanAnalyzerMysql.php @@ -37,6 +37,7 @@ public function analyze(string $query): QueryPlanResult if ($this->connection instanceof PDO) { $stmt = $this->connection->query('EXPLAIN '.$query); + // @phpstan-ignore-next-line return $this->buildResult($stmt); } else { $result = $this->connection->query('EXPLAIN '.$query); diff --git a/tests/default/config/.phpstan-dba-mysqli.cache b/tests/default/config/.phpstan-dba-mysqli.cache index ab7cc79bb..8a36e3bca 100644 --- a/tests/default/config/.phpstan-dba-mysqli.cache +++ b/tests/default/config/.phpstan-dba-mysqli.cache @@ -3274,10 +3274,6 @@ FROM ada' => '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', 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/default/config/.phpstan-dba-pdo-mysql.cache b/tests/default/config/.phpstan-dba-pdo-mysql.cache index 695a6ffc6..620e34e6d 100644 --- a/tests/default/config/.phpstan-dba-pdo-mysql.cache +++ b/tests/default/config/.phpstan-dba-pdo-mysql.cache @@ -3274,10 +3274,6 @@ FROM ada' => 'message' => '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', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache b/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache index 3722c1430..9bb86605e 100644 --- a/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache +++ b/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache @@ -3274,10 +3274,6 @@ FROM ada' => 'message' => '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', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/rules/config/.phpstan-dba-mysqli.cache b/tests/rules/config/.phpstan-dba-mysqli.cache index 90bd7f111..df6755cf6 100644 --- a/tests/rules/config/.phpstan-dba-mysqli.cache +++ b/tests/rules/config/.phpstan-dba-mysqli.cache @@ -75,6 +75,312 @@ 5 => NULL, ), ), + 'SELECT * FROM `ada` WHERE adaid = 1' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), + 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), 'SELECT * FROM ada GROUP BY doesNotExist' => array ( 'error' => @@ -82,42 +388,352 @@ 'message' => 'Unknown column \'doesNotExist\' in \'group statement\'', 'code' => 1054, )), + ), + 'SELECT * FROM ada ORDER BY doesNotExist' => + array ( + 'error' => + staabm\PHPStanDba\Error::__set_state(array( + 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', + 'code' => 1054, + )), + ), + 'SELECT * FROM ada WHERE doesNotExist=1' => + array ( + 'error' => + staabm\PHPStanDba\Error::__set_state(array( + 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', + 'code' => 1054, + )), + ), + 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => + array ( 'result' => array ( - 5 => NULL, + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), ), ), - 'SELECT * FROM ada ORDER BY doesNotExist' => + 'SELECT * FROM unknown_table' => array ( 'error' => staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', - 'code' => 1054, + 'message' => 'Table \'phpstan_dba.unknown_table\' doesn\'t exist', + 'code' => 1146, )), - 'result' => - array ( - 5 => NULL, - ), ), - 'SELECT * FROM ada WHERE doesNotExist=1' => + 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( - 'error' => - staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', - 'code' => 1054, - )), 'result' => array ( - 5 => NULL, + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 5, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 8 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 4, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 8 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 4, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 8 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), ), ), - 'SELECT * FROM unknown_table' => + 'SELECT FROM WHERE' => array ( - 'error' => - staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Table \'phpstan_dba.unknown_table\' doesn\'t exist', - 'code' => 1146, - )), 'result' => array ( 5 => NULL, @@ -200,10 +816,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'field list\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email FROM ada WHERE gesperrt=:gesperrt' => array ( @@ -276,11 +888,6 @@ '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', 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - 3 => NULL, - ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -539,10 +1146,6 @@ '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, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( diff --git a/tests/rules/config/.phpstan-dba-pdo-mysql.cache b/tests/rules/config/.phpstan-dba-pdo-mysql.cache index ca2966b23..3d4f3e503 100644 --- a/tests/rules/config/.phpstan-dba-pdo-mysql.cache +++ b/tests/rules/config/.phpstan-dba-pdo-mysql.cache @@ -75,6 +75,312 @@ 5 => NULL, ), ), + 'SELECT * FROM `ada` WHERE adaid = 1' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), + 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), 'SELECT * FROM ada GROUP BY doesNotExist' => array ( 'error' => @@ -82,42 +388,352 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'group statement\'', 'code' => '42S22', )), + ), + 'SELECT * FROM ada ORDER BY doesNotExist' => + array ( + 'error' => + staabm\PHPStanDba\Error::__set_state(array( + 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'order clause\'', + 'code' => '42S22', + )), + ), + 'SELECT * FROM ada WHERE doesNotExist=1' => + array ( + 'error' => + staabm\PHPStanDba\Error::__set_state(array( + 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'where clause\'', + 'code' => '42S22', + )), + ), + 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => + array ( 'result' => array ( - 5 => NULL, + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), ), ), - 'SELECT * FROM ada ORDER BY doesNotExist' => + 'SELECT * FROM unknown_table' => array ( 'error' => staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'order clause\'', - 'code' => '42S22', + 'message' => 'SQLSTATE[42S02]: Base table or view not found: 1146 Table \'phpstan_dba.unknown_table\' doesn\'t exist', + 'code' => '42S02', )), - 'result' => - array ( - 5 => NULL, - ), ), - 'SELECT * FROM ada WHERE doesNotExist=1' => + 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( - 'error' => - staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'where clause\'', - 'code' => '42S22', - )), 'result' => array ( - 5 => NULL, + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 5, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 8 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 4, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 8 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 4, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 8 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), ), ), - 'SELECT * FROM unknown_table' => + 'SELECT FROM WHERE' => array ( - 'error' => - staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'SQLSTATE[42S02]: Base table or view not found: 1146 Table \'phpstan_dba.unknown_table\' doesn\'t exist', - 'code' => '42S02', - )), 'result' => array ( 5 => NULL, @@ -200,10 +816,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'field list\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email FROM ada WHERE gesperrt=:gesperrt' => array ( @@ -276,11 +888,6 @@ 'message' => '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', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - 3 => NULL, - ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -539,10 +1146,6 @@ 'message' => '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 \'FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( diff --git a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache index 2e45270ed..5321a920a 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache @@ -75,6 +75,468 @@ 5 => NULL, ), ), + 'SELECT * FROM `ada` WHERE adaid = 1' => + array ( + 'error' => NULL, + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), + 'SELECT * FROM `ada` WHERE email = \'1970-01-01\'' => + array ( + 'error' => NULL, + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), + 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => + array ( + 'error' => NULL, + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), 'SELECT * FROM ada GROUP BY doesNotExist' => array ( 'error' => @@ -87,41 +549,368 @@ 5 => NULL, ), ), - 'SELECT * FROM ada ORDER BY doesNotExist' => + 'SELECT * FROM ada ORDER BY doesNotExist' => + array ( + 'error' => + staabm\PHPStanDba\Error::__set_state(array( + 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', + 'code' => 1054, + )), + 'result' => + array ( + 5 => NULL, + ), + ), + 'SELECT * FROM ada WHERE doesNotExist=1' => + array ( + 'error' => + staabm\PHPStanDba\Error::__set_state(array( + 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', + 'code' => 1054, + )), + 'result' => + array ( + 5 => NULL, + ), + ), + 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => + array ( + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), + 'SELECT * FROM unknown_table' => array ( 'error' => staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', - 'code' => 1054, + 'message' => 'Table \'phpstan_dba.unknown_table\' doesn\'t exist', + 'code' => 1146, )), 'result' => array ( 5 => NULL, ), ), - 'SELECT * FROM ada WHERE doesNotExist=1' => + 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( - 'error' => - staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', - 'code' => 1054, - )), 'result' => array ( - 5 => NULL, + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 5, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 8 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 4, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 8 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 4, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 8 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), ), ), - 'SELECT * FROM unknown_table' => + 'SELECT FROM WHERE' => array ( 'error' => staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'Table \'phpstan_dba.unknown_table\' doesn\'t exist', - 'code' => 1146, + '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 WHERE LIMIT 0\' at line 1', + 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT adaid FROM ada WHERE email = \'1970-01-01\'' => array ( diff --git a/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache b/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache index 2b191b5d8..0f6491e9a 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache @@ -75,6 +75,314 @@ 5 => NULL, ), ), + 'SELECT * FROM `ada` WHERE adaid = 1' => + array ( + 'error' => NULL, + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), + 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => + array ( + 'error' => NULL, + 'result' => + array ( + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), + ), + ), 'SELECT * FROM ada GROUP BY doesNotExist' => array ( 'error' => @@ -82,41 +390,358 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'group statement\'', 'code' => '42S22', )), + ), + 'SELECT * FROM ada ORDER BY doesNotExist' => + array ( + 'error' => + staabm\PHPStanDba\Error::__set_state(array( + 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'order clause\'', + 'code' => '42S22', + )), + ), + 'SELECT * FROM ada WHERE doesNotExist=1' => + array ( + 'error' => + staabm\PHPStanDba\Error::__set_state(array( + 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'where clause\'', + 'code' => '42S22', + )), + ), + 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => + array ( + 'error' => NULL, 'result' => array ( - 5 => NULL, + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 4, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), ), ), - 'SELECT * FROM ada ORDER BY doesNotExist' => + 'SELECT * FROM unknown_table' => array ( 'error' => staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'order clause\'', - 'code' => '42S22', + 'message' => 'SQLSTATE[42S02]: Base table or view not found: 1146 Table \'phpstan_dba.unknown_table\' doesn\'t exist', + 'code' => '42S02', )), - 'result' => - array ( - 5 => NULL, - ), ), - 'SELECT * FROM ada WHERE doesNotExist=1' => + 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( - 'error' => - staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'where clause\'', - 'code' => '42S22', - )), + 'error' => NULL, 'result' => array ( - 5 => NULL, + 5 => + PHPStan\Type\Constant\ConstantArrayType::__set_state(array( + 'allArrays' => NULL, + 'nextAutoIndexes' => + array ( + 0 => 5, + ), + 'keyTypes' => + array ( + 0 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 2 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 4 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 5 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 8 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 4, + )), + ), + 'valueTypes' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 2 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 3 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 4 => + PHPStan\Type\StringType::__set_state(array( + )), + 5 => + PHPStan\Type\StringType::__set_state(array( + )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 8 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + ), + 'optionalKeys' => + array ( + ), + 'keyType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => true, + 'types' => + array ( + 0 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 0, + )), + 1 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 1, + )), + 2 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 2, + )), + 3 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), + 4 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 4, + )), + 5 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'adaid', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'email', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 8 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', + 'isClassString' => false, + )), + ), + )), + 'itemType' => + PHPStan\Type\UnionType::__set_state(array( + 'sortedTypes' => false, + 'types' => + array ( + 0 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, + )), + 1 => + PHPStan\Type\StringType::__set_state(array( + )), + ), + )), + )), ), ), - 'SELECT * FROM unknown_table' => + 'SELECT FROM WHERE' => array ( 'error' => staabm\PHPStanDba\Error::__set_state(array( - 'message' => 'SQLSTATE[42S02]: Base table or view not found: 1146 Table \'phpstan_dba.unknown_table\' doesn\'t exist', - 'code' => '42S02', + 'message' => '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 \'FROM WHERE LIMIT 0\' at line 1', + 'code' => '42000', )), 'result' => array ( @@ -228,10 +853,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'field list\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email FROM ada WHERE adaid IN (\'1\')' => array ( @@ -277,11 +898,6 @@ 'message' => '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', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - 3 => NULL, - ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -290,10 +906,6 @@ 'message' => '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 \'gesperrt freigabe1u1 FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada @@ -470,10 +1082,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'xy\' in \'group statement\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada WHERE adaid = \'1\'' => array ( @@ -616,7 +1224,6 @@ ), 'SELECT email, adaid FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -723,10 +1330,6 @@ 'message' => '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 \'FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( @@ -737,7 +1340,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada' => array ( - 'error' => NULL, 'result' => array ( 3 => @@ -998,7 +1600,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -1152,7 +1753,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -1493,11 +2093,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'asdsa\' in \'where clause\'', 'code' => '42S22', )), - 'result' => - array ( - 3 => NULL, - 5 => NULL, - ), ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE gesperrt=\'1\'' => array ( diff --git a/tests/rules/data/query-plan-analyzer.php b/tests/rules/data/query-plan-analyzer.php index 7adfac491..ee056447a 100644 --- a/tests/rules/data/query-plan-analyzer.php +++ b/tests/rules/data/query-plan-analyzer.php @@ -19,12 +19,12 @@ public function noindexDbal(Connection $conn): void public function noindexPreparedDbal(Connection $conn, string $email): void { - $conn->executeQuery("SELECT * FROM ada WHERE email = ?", [$email]); + $conn->executeQuery('SELECT * FROM ada WHERE email = ?', [$email]); } public function syntaxError(Connection $conn): void { - $conn->executeQuery("SELECT FROM WHERE"); + $conn->executeQuery('SELECT FROM WHERE'); } public function indexed(PDO $pdo, int $adaid): void From bacd795aca71c116826088e2d7e9b3ad98fd5030 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 24 May 2022 22:12:45 +0200 Subject: [PATCH 15/24] fix --- src/Analyzer/QueryPlanAnalyzerMysql.php | 2 +- .../default/config/.phpstan-dba-mysqli.cache | 4 ++ .../config/.phpstan-dba-pdo-mysql.cache | 4 ++ .../.phpunit-phpstan-dba-pdo-mysql.cache | 4 ++ tests/rules/QueryPlanAnalyzerRuleTest.php | 4 ++ tests/rules/config/.phpstan-dba-mysqli.cache | 29 ++++++++++ .../rules/config/.phpstan-dba-pdo-mysql.cache | 29 ++++++++++ .../.phpunit-phpstan-dba-pdo-mysql.cache | 54 ++++++++++++++++--- 8 files changed, 121 insertions(+), 9 deletions(-) diff --git a/src/Analyzer/QueryPlanAnalyzerMysql.php b/src/Analyzer/QueryPlanAnalyzerMysql.php index 4989bc41f..9edbf91cc 100644 --- a/src/Analyzer/QueryPlanAnalyzerMysql.php +++ b/src/Analyzer/QueryPlanAnalyzerMysql.php @@ -52,7 +52,7 @@ public function analyze(string $query): QueryPlanResult /** * @param \IteratorAggregate $it */ - private function buildResult(\IteratorAggregate $it): QueryPlanResult + private function buildResult($it): QueryPlanResult { $result = new QueryPlanResult(); $allowedUnindexedReads = QueryReflection::getRuntimeConfiguration()->getNumberOfAllowedUnindexedReads(); diff --git a/tests/default/config/.phpstan-dba-mysqli.cache b/tests/default/config/.phpstan-dba-mysqli.cache index 8a36e3bca..ab7cc79bb 100644 --- a/tests/default/config/.phpstan-dba-mysqli.cache +++ b/tests/default/config/.phpstan-dba-mysqli.cache @@ -3274,6 +3274,10 @@ FROM ada' => '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', 'code' => 1064, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/default/config/.phpstan-dba-pdo-mysql.cache b/tests/default/config/.phpstan-dba-pdo-mysql.cache index 620e34e6d..695a6ffc6 100644 --- a/tests/default/config/.phpstan-dba-pdo-mysql.cache +++ b/tests/default/config/.phpstan-dba-pdo-mysql.cache @@ -3274,6 +3274,10 @@ FROM ada' => 'message' => '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', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache b/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache index 9bb86605e..3722c1430 100644 --- a/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache +++ b/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache @@ -3274,6 +3274,10 @@ FROM ada' => 'message' => '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', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/rules/QueryPlanAnalyzerRuleTest.php b/tests/rules/QueryPlanAnalyzerRuleTest.php index 5f5bf1a87..cbeaed656 100644 --- a/tests/rules/QueryPlanAnalyzerRuleTest.php +++ b/tests/rules/QueryPlanAnalyzerRuleTest.php @@ -38,6 +38,10 @@ public static function getAdditionalConfigFiles(): array public function testNotUsingIndex(): void { + if ('pdo-pgsql' === getenv('DBA_REFLECTOR')) { + $this->markTestSkipped('This test is not supported on PostgreSQL'); + } + $this->numberOfAllowedUnindexedReads = true; $this->analyse([__DIR__.'/data/query-plan-analyzer.php'], [ diff --git a/tests/rules/config/.phpstan-dba-mysqli.cache b/tests/rules/config/.phpstan-dba-mysqli.cache index df6755cf6..4d45fac36 100644 --- a/tests/rules/config/.phpstan-dba-mysqli.cache +++ b/tests/rules/config/.phpstan-dba-mysqli.cache @@ -388,6 +388,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'group statement\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -396,6 +400,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -404,6 +412,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -565,6 +577,10 @@ 'message' => 'Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => 1146, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( @@ -816,6 +832,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'field list\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email FROM ada WHERE gesperrt=:gesperrt' => array ( @@ -888,6 +908,11 @@ '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', 'code' => 1064, )), + 'result' => + array ( + 5 => NULL, + 3 => NULL, + ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -1146,6 +1171,10 @@ '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, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( diff --git a/tests/rules/config/.phpstan-dba-pdo-mysql.cache b/tests/rules/config/.phpstan-dba-pdo-mysql.cache index 3d4f3e503..14bc15ad9 100644 --- a/tests/rules/config/.phpstan-dba-pdo-mysql.cache +++ b/tests/rules/config/.phpstan-dba-pdo-mysql.cache @@ -388,6 +388,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'group statement\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -396,6 +400,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'order clause\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -404,6 +412,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'where clause\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -565,6 +577,10 @@ 'message' => 'SQLSTATE[42S02]: Base table or view not found: 1146 Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => '42S02', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( @@ -816,6 +832,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'field list\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email FROM ada WHERE gesperrt=:gesperrt' => array ( @@ -888,6 +908,11 @@ 'message' => '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', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + 3 => NULL, + ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -1146,6 +1171,10 @@ 'message' => '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 \'FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( diff --git a/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache b/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache index 0f6491e9a..74ed8ae99 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache @@ -77,7 +77,6 @@ ), 'SELECT * FROM `ada` WHERE adaid = 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -231,7 +230,6 @@ ), 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -390,6 +388,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'group statement\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -398,6 +400,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'order clause\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -406,10 +412,13 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'where clause\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -568,10 +577,13 @@ 'message' => 'SQLSTATE[42S02]: Base table or view not found: 1146 Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => '42S02', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -743,10 +755,6 @@ 'message' => '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 \'FROM WHERE LIMIT 0\' at line 1', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT adaid FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -853,6 +861,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'field list\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email FROM ada WHERE adaid IN (\'1\')' => array ( @@ -898,6 +910,11 @@ 'message' => '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', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + 3 => NULL, + ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -906,6 +923,10 @@ 'message' => '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 \'gesperrt freigabe1u1 FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada @@ -1082,6 +1103,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'xy\' in \'group statement\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada WHERE adaid = \'1\'' => array ( @@ -1224,6 +1249,7 @@ ), 'SELECT email, adaid FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -1330,6 +1356,10 @@ 'message' => '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 \'FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( @@ -1340,6 +1370,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada' => array ( + 'error' => NULL, 'result' => array ( 3 => @@ -1600,6 +1631,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -1753,6 +1785,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -2093,6 +2126,11 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'asdsa\' in \'where clause\'', 'code' => '42S22', )), + 'result' => + array ( + 3 => NULL, + 5 => NULL, + ), ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE gesperrt=\'1\'' => array ( From d23d0b5e740056f23e3c940f3089e76e27c2c011 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 24 May 2022 22:16:27 +0200 Subject: [PATCH 16/24] Update QueryPlanAnalyzerRuleTest.php --- tests/rules/QueryPlanAnalyzerRuleTest.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/rules/QueryPlanAnalyzerRuleTest.php b/tests/rules/QueryPlanAnalyzerRuleTest.php index cbeaed656..480292f6d 100644 --- a/tests/rules/QueryPlanAnalyzerRuleTest.php +++ b/tests/rules/QueryPlanAnalyzerRuleTest.php @@ -39,7 +39,11 @@ public static function getAdditionalConfigFiles(): array public function testNotUsingIndex(): void { if ('pdo-pgsql' === getenv('DBA_REFLECTOR')) { - $this->markTestSkipped('This test is not supported on PostgreSQL'); + $this->markTestSkipped('query plan analyzer is not yet implemented for pgsql'); + } + + if ('recording' !== getenv('DBA_MODE')) { + $this->markTestSkipped('query plan analyzer requires a active database connection'); } $this->numberOfAllowedUnindexedReads = true; From b19b74efa98c89bed8891e579ca033acf3f1d038 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 24 May 2022 22:19:38 +0200 Subject: [PATCH 17/24] fix --- .phpstan-dba-mysqli.cache | 6 +-- .../default/config/.phpstan-dba-mysqli.cache | 4 -- .../config/.phpstan-dba-pdo-mysql.cache | 4 -- .../config/.phpunit-phpstan-dba-mysqli.cache | 4 ++ .../.phpunit-phpstan-dba-pdo-mysql.cache | 4 -- tests/rules/config/.phpstan-dba-mysqli.cache | 29 ---------- .../rules/config/.phpstan-dba-pdo-mysql.cache | 29 ---------- .../config/.phpunit-phpstan-dba-mysqli.cache | 54 +++---------------- .../.phpunit-phpstan-dba-pdo-mysql.cache | 54 +++---------------- tests/schema.sql | 6 +++ 10 files changed, 27 insertions(+), 167 deletions(-) diff --git a/.phpstan-dba-mysqli.cache b/.phpstan-dba-mysqli.cache index ebe33e71a..99730a835 100644 --- a/.phpstan-dba-mysqli.cache +++ b/.phpstan-dba-mysqli.cache @@ -770,7 +770,7 @@ WHERE table_name = \'1970-01-01\'' => )), 2 => PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => true, + 'sortedTypes' => false, 'types' => array ( 0 => @@ -783,7 +783,7 @@ WHERE table_name = \'1970-01-01\'' => )), 3 => PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => true, + 'sortedTypes' => false, 'types' => array ( 0 => @@ -840,7 +840,7 @@ WHERE table_name = \'1970-01-01\'' => )), 'itemType' => PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => true, + 'sortedTypes' => false, 'types' => array ( 0 => diff --git a/tests/default/config/.phpstan-dba-mysqli.cache b/tests/default/config/.phpstan-dba-mysqli.cache index ab7cc79bb..8a36e3bca 100644 --- a/tests/default/config/.phpstan-dba-mysqli.cache +++ b/tests/default/config/.phpstan-dba-mysqli.cache @@ -3274,10 +3274,6 @@ FROM ada' => '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', 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/default/config/.phpstan-dba-pdo-mysql.cache b/tests/default/config/.phpstan-dba-pdo-mysql.cache index 695a6ffc6..620e34e6d 100644 --- a/tests/default/config/.phpstan-dba-pdo-mysql.cache +++ b/tests/default/config/.phpstan-dba-pdo-mysql.cache @@ -3274,10 +3274,6 @@ FROM ada' => 'message' => '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', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/default/config/.phpunit-phpstan-dba-mysqli.cache b/tests/default/config/.phpunit-phpstan-dba-mysqli.cache index 44fe9fd3a..95dd07083 100644 --- a/tests/default/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/default/config/.phpunit-phpstan-dba-mysqli.cache @@ -3394,6 +3394,10 @@ FROM ada' => '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', 'code' => 1064, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache b/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache index 3722c1430..9bb86605e 100644 --- a/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache +++ b/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache @@ -3274,10 +3274,6 @@ FROM ada' => 'message' => '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', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/rules/config/.phpstan-dba-mysqli.cache b/tests/rules/config/.phpstan-dba-mysqli.cache index 4d45fac36..df6755cf6 100644 --- a/tests/rules/config/.phpstan-dba-mysqli.cache +++ b/tests/rules/config/.phpstan-dba-mysqli.cache @@ -388,10 +388,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'group statement\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -400,10 +396,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -412,10 +404,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -577,10 +565,6 @@ 'message' => 'Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => 1146, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( @@ -832,10 +816,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'field list\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email FROM ada WHERE gesperrt=:gesperrt' => array ( @@ -908,11 +888,6 @@ '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', 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - 3 => NULL, - ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -1171,10 +1146,6 @@ '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, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( diff --git a/tests/rules/config/.phpstan-dba-pdo-mysql.cache b/tests/rules/config/.phpstan-dba-pdo-mysql.cache index 14bc15ad9..3d4f3e503 100644 --- a/tests/rules/config/.phpstan-dba-pdo-mysql.cache +++ b/tests/rules/config/.phpstan-dba-pdo-mysql.cache @@ -388,10 +388,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'group statement\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -400,10 +396,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'order clause\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -412,10 +404,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'where clause\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -577,10 +565,6 @@ 'message' => 'SQLSTATE[42S02]: Base table or view not found: 1146 Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => '42S02', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( @@ -832,10 +816,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'field list\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email FROM ada WHERE gesperrt=:gesperrt' => array ( @@ -908,11 +888,6 @@ 'message' => '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', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - 3 => NULL, - ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -1171,10 +1146,6 @@ 'message' => '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 \'FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( diff --git a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache index 5321a920a..672406cdb 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache @@ -77,7 +77,6 @@ ), 'SELECT * FROM `ada` WHERE adaid = 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -385,7 +384,6 @@ ), 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -544,10 +542,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'group statement\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -556,10 +550,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -568,13 +558,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -733,13 +720,10 @@ 'message' => 'Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => 1146, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -911,6 +895,10 @@ '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 WHERE LIMIT 0\' at line 1', 'code' => 1064, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT adaid FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -1017,10 +1005,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'field list\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email FROM ada WHERE adaid IN (\'1\')' => array ( @@ -1066,11 +1050,6 @@ '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', 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - 3 => NULL, - ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -1079,10 +1058,6 @@ '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', 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada @@ -1259,10 +1234,6 @@ 'message' => 'Unknown column \'xy\' in \'group statement\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada WHERE adaid = \'1\'' => array ( @@ -1405,7 +1376,6 @@ ), 'SELECT email, adaid FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -1512,10 +1482,6 @@ '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, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( @@ -1526,7 +1492,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada' => array ( - 'error' => NULL, 'result' => array ( 3 => @@ -1787,7 +1752,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -1941,7 +1905,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -2282,11 +2245,6 @@ 'message' => 'Unknown column \'asdsa\' in \'where clause\'', 'code' => 1054, )), - 'result' => - array ( - 3 => NULL, - 5 => NULL, - ), ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE gesperrt=\'1\'' => array ( diff --git a/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache b/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache index 74ed8ae99..0f6491e9a 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache @@ -77,6 +77,7 @@ ), 'SELECT * FROM `ada` WHERE adaid = 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -230,6 +231,7 @@ ), 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -388,10 +390,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'group statement\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -400,10 +398,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'order clause\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -412,13 +406,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'where clause\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -577,13 +568,10 @@ 'message' => 'SQLSTATE[42S02]: Base table or view not found: 1146 Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => '42S02', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -755,6 +743,10 @@ 'message' => '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 \'FROM WHERE LIMIT 0\' at line 1', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT adaid FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -861,10 +853,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'field list\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email FROM ada WHERE adaid IN (\'1\')' => array ( @@ -910,11 +898,6 @@ 'message' => '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', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - 3 => NULL, - ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -923,10 +906,6 @@ 'message' => '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 \'gesperrt freigabe1u1 FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada @@ -1103,10 +1082,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'xy\' in \'group statement\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada WHERE adaid = \'1\'' => array ( @@ -1249,7 +1224,6 @@ ), 'SELECT email, adaid FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -1356,10 +1330,6 @@ 'message' => '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 \'FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( @@ -1370,7 +1340,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada' => array ( - 'error' => NULL, 'result' => array ( 3 => @@ -1631,7 +1600,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -1785,7 +1753,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -2126,11 +2093,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'asdsa\' in \'where clause\'', 'code' => '42S22', )), - 'result' => - array ( - 3 => NULL, - 5 => NULL, - ), ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE gesperrt=\'1\'' => array ( diff --git a/tests/schema.sql b/tests/schema.sql index abd893ef1..94ef0de7e 100644 --- a/tests/schema.sql +++ b/tests/schema.sql @@ -12,6 +12,12 @@ CREATE TABLE `ada` ( ALTER TABLE `ada` ADD PRIMARY KEY (`adaid`); +INSERT INTO `ada` (`adaid`, `gesperrt`, `email`, `freigabe1u1`) +VALUES + (1, 0, 'test@example.com', 0), + (3, 0, 'test@example.com', 0), + (2, 1, 'another@example.com', 1); + CREATE TABLE `ak` ( `akid` int(11) NOT NULL DEFAULT '0', From 2d77d47d1281b46737a64594cef3fe4a05396853 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 24 May 2022 22:29:09 +0200 Subject: [PATCH 18/24] record --- .phpstan-dba-mysqli.cache | 6 +-- .phpstan-dba-pdo-mysql.cache | 6 +-- .../default/config/.phpstan-dba-mysqli.cache | 4 ++ .../config/.phpstan-dba-pdo-mysql.cache | 4 ++ .../config/.phpunit-phpstan-dba-mysqli.cache | 4 -- .../.phpunit-phpstan-dba-pdo-mysql.cache | 4 ++ tests/rules/config/.phpstan-dba-mysqli.cache | 29 ++++++++++ .../rules/config/.phpstan-dba-pdo-mysql.cache | 29 ++++++++++ .../config/.phpunit-phpstan-dba-mysqli.cache | 54 ++++++++++++++++--- .../.phpunit-phpstan-dba-pdo-mysql.cache | 54 ++++++++++++++++--- 10 files changed, 170 insertions(+), 24 deletions(-) diff --git a/.phpstan-dba-mysqli.cache b/.phpstan-dba-mysqli.cache index 99730a835..ebe33e71a 100644 --- a/.phpstan-dba-mysqli.cache +++ b/.phpstan-dba-mysqli.cache @@ -770,7 +770,7 @@ WHERE table_name = \'1970-01-01\'' => )), 2 => PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => false, + 'sortedTypes' => true, 'types' => array ( 0 => @@ -783,7 +783,7 @@ WHERE table_name = \'1970-01-01\'' => )), 3 => PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => false, + 'sortedTypes' => true, 'types' => array ( 0 => @@ -840,7 +840,7 @@ WHERE table_name = \'1970-01-01\'' => )), 'itemType' => PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => false, + 'sortedTypes' => true, 'types' => array ( 0 => diff --git a/.phpstan-dba-pdo-mysql.cache b/.phpstan-dba-pdo-mysql.cache index c5544ecca..5516075c0 100644 --- a/.phpstan-dba-pdo-mysql.cache +++ b/.phpstan-dba-pdo-mysql.cache @@ -714,7 +714,7 @@ WHERE table_name = \'1970-01-01\'' => )), 2 => PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => false, + 'sortedTypes' => true, 'types' => array ( 0 => @@ -727,7 +727,7 @@ WHERE table_name = \'1970-01-01\'' => )), 3 => PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => false, + 'sortedTypes' => true, 'types' => array ( 0 => @@ -784,7 +784,7 @@ WHERE table_name = \'1970-01-01\'' => )), 'itemType' => PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => false, + 'sortedTypes' => true, 'types' => array ( 0 => diff --git a/tests/default/config/.phpstan-dba-mysqli.cache b/tests/default/config/.phpstan-dba-mysqli.cache index 8a36e3bca..ab7cc79bb 100644 --- a/tests/default/config/.phpstan-dba-mysqli.cache +++ b/tests/default/config/.phpstan-dba-mysqli.cache @@ -3274,6 +3274,10 @@ FROM ada' => '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', 'code' => 1064, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/default/config/.phpstan-dba-pdo-mysql.cache b/tests/default/config/.phpstan-dba-pdo-mysql.cache index 620e34e6d..695a6ffc6 100644 --- a/tests/default/config/.phpstan-dba-pdo-mysql.cache +++ b/tests/default/config/.phpstan-dba-pdo-mysql.cache @@ -3274,6 +3274,10 @@ FROM ada' => 'message' => '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', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/default/config/.phpunit-phpstan-dba-mysqli.cache b/tests/default/config/.phpunit-phpstan-dba-mysqli.cache index 95dd07083..44fe9fd3a 100644 --- a/tests/default/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/default/config/.phpunit-phpstan-dba-mysqli.cache @@ -3394,10 +3394,6 @@ FROM ada' => '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', 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache b/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache index 9bb86605e..3722c1430 100644 --- a/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache +++ b/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache @@ -3274,6 +3274,10 @@ FROM ada' => 'message' => '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', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/rules/config/.phpstan-dba-mysqli.cache b/tests/rules/config/.phpstan-dba-mysqli.cache index df6755cf6..4d45fac36 100644 --- a/tests/rules/config/.phpstan-dba-mysqli.cache +++ b/tests/rules/config/.phpstan-dba-mysqli.cache @@ -388,6 +388,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'group statement\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -396,6 +400,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -404,6 +412,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -565,6 +577,10 @@ 'message' => 'Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => 1146, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( @@ -816,6 +832,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'field list\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email FROM ada WHERE gesperrt=:gesperrt' => array ( @@ -888,6 +908,11 @@ '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', 'code' => 1064, )), + 'result' => + array ( + 5 => NULL, + 3 => NULL, + ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -1146,6 +1171,10 @@ '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, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( diff --git a/tests/rules/config/.phpstan-dba-pdo-mysql.cache b/tests/rules/config/.phpstan-dba-pdo-mysql.cache index 3d4f3e503..14bc15ad9 100644 --- a/tests/rules/config/.phpstan-dba-pdo-mysql.cache +++ b/tests/rules/config/.phpstan-dba-pdo-mysql.cache @@ -388,6 +388,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'group statement\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -396,6 +400,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'order clause\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -404,6 +412,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'where clause\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -565,6 +577,10 @@ 'message' => 'SQLSTATE[42S02]: Base table or view not found: 1146 Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => '42S02', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( @@ -816,6 +832,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'field list\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email FROM ada WHERE gesperrt=:gesperrt' => array ( @@ -888,6 +908,11 @@ 'message' => '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', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + 3 => NULL, + ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -1146,6 +1171,10 @@ 'message' => '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 \'FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( diff --git a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache index 672406cdb..5321a920a 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache @@ -77,6 +77,7 @@ ), 'SELECT * FROM `ada` WHERE adaid = 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -384,6 +385,7 @@ ), 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -542,6 +544,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'group statement\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -550,6 +556,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -558,10 +568,13 @@ 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -720,10 +733,13 @@ 'message' => 'Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => 1146, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -895,10 +911,6 @@ '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 WHERE LIMIT 0\' at line 1', 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT adaid FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -1005,6 +1017,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'field list\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email FROM ada WHERE adaid IN (\'1\')' => array ( @@ -1050,6 +1066,11 @@ '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', 'code' => 1064, )), + 'result' => + array ( + 5 => NULL, + 3 => NULL, + ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -1058,6 +1079,10 @@ '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', 'code' => 1064, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada @@ -1234,6 +1259,10 @@ 'message' => 'Unknown column \'xy\' in \'group statement\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada WHERE adaid = \'1\'' => array ( @@ -1376,6 +1405,7 @@ ), 'SELECT email, adaid FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -1482,6 +1512,10 @@ '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, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( @@ -1492,6 +1526,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada' => array ( + 'error' => NULL, 'result' => array ( 3 => @@ -1752,6 +1787,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -1905,6 +1941,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -2245,6 +2282,11 @@ 'message' => 'Unknown column \'asdsa\' in \'where clause\'', 'code' => 1054, )), + 'result' => + array ( + 3 => NULL, + 5 => NULL, + ), ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE gesperrt=\'1\'' => array ( diff --git a/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache b/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache index 0f6491e9a..74ed8ae99 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache @@ -77,7 +77,6 @@ ), 'SELECT * FROM `ada` WHERE adaid = 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -231,7 +230,6 @@ ), 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -390,6 +388,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'group statement\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -398,6 +400,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'order clause\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -406,10 +412,13 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'where clause\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -568,10 +577,13 @@ 'message' => 'SQLSTATE[42S02]: Base table or view not found: 1146 Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => '42S02', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -743,10 +755,6 @@ 'message' => '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 \'FROM WHERE LIMIT 0\' at line 1', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT adaid FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -853,6 +861,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'field list\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email FROM ada WHERE adaid IN (\'1\')' => array ( @@ -898,6 +910,11 @@ 'message' => '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', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + 3 => NULL, + ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -906,6 +923,10 @@ 'message' => '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 \'gesperrt freigabe1u1 FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada @@ -1082,6 +1103,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'xy\' in \'group statement\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada WHERE adaid = \'1\'' => array ( @@ -1224,6 +1249,7 @@ ), 'SELECT email, adaid FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -1330,6 +1356,10 @@ 'message' => '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 \'FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( @@ -1340,6 +1370,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada' => array ( + 'error' => NULL, 'result' => array ( 3 => @@ -1600,6 +1631,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -1753,6 +1785,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -2093,6 +2126,11 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'asdsa\' in \'where clause\'', 'code' => '42S22', )), + 'result' => + array ( + 3 => NULL, + 5 => NULL, + ), ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE gesperrt=\'1\'' => array ( From dd55bf1ba4b76e84f39eedd55d3eb5d9e70b1b17 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 24 May 2022 22:36:44 +0200 Subject: [PATCH 19/24] fix --- .phpstan-dba-mysqli.cache | 6 ++-- src/QueryReflection/QueryReflection.php | 4 +++ .../config/.phpstan-dba-pdo-mysql.cache | 4 --- .../rules/config/.phpstan-dba-pdo-mysql.cache | 29 ------------------- tests/rules/data/query-plan-analyzer.php | 8 +++++ 5 files changed, 15 insertions(+), 36 deletions(-) diff --git a/.phpstan-dba-mysqli.cache b/.phpstan-dba-mysqli.cache index ebe33e71a..99730a835 100644 --- a/.phpstan-dba-mysqli.cache +++ b/.phpstan-dba-mysqli.cache @@ -770,7 +770,7 @@ WHERE table_name = \'1970-01-01\'' => )), 2 => PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => true, + 'sortedTypes' => false, 'types' => array ( 0 => @@ -783,7 +783,7 @@ WHERE table_name = \'1970-01-01\'' => )), 3 => PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => true, + 'sortedTypes' => false, 'types' => array ( 0 => @@ -840,7 +840,7 @@ WHERE table_name = \'1970-01-01\'' => )), 'itemType' => PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => true, + 'sortedTypes' => false, 'types' => array ( 0 => diff --git a/src/QueryReflection/QueryReflection.php b/src/QueryReflection/QueryReflection.php index 71b416e41..e93191afa 100644 --- a/src/QueryReflection/QueryReflection.php +++ b/src/QueryReflection/QueryReflection.php @@ -436,6 +436,10 @@ public function analyzeQueryPlan(Scope $scope, Expr $queryExpr, ?Type $parameter continue; } + if ('SELECT' !== self::getQueryType($queryString)) { + continue; + } + if ($reflector->validateQueryString($queryString) instanceof Error) { continue; } diff --git a/tests/default/config/.phpstan-dba-pdo-mysql.cache b/tests/default/config/.phpstan-dba-pdo-mysql.cache index 695a6ffc6..620e34e6d 100644 --- a/tests/default/config/.phpstan-dba-pdo-mysql.cache +++ b/tests/default/config/.phpstan-dba-pdo-mysql.cache @@ -3274,10 +3274,6 @@ FROM ada' => 'message' => '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', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/rules/config/.phpstan-dba-pdo-mysql.cache b/tests/rules/config/.phpstan-dba-pdo-mysql.cache index 14bc15ad9..3d4f3e503 100644 --- a/tests/rules/config/.phpstan-dba-pdo-mysql.cache +++ b/tests/rules/config/.phpstan-dba-pdo-mysql.cache @@ -388,10 +388,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'group statement\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -400,10 +396,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'order clause\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -412,10 +404,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'where clause\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -577,10 +565,6 @@ 'message' => 'SQLSTATE[42S02]: Base table or view not found: 1146 Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => '42S02', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( @@ -832,10 +816,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'field list\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email FROM ada WHERE gesperrt=:gesperrt' => array ( @@ -908,11 +888,6 @@ 'message' => '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', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - 3 => NULL, - ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -1171,10 +1146,6 @@ 'message' => '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 \'FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( diff --git a/tests/rules/data/query-plan-analyzer.php b/tests/rules/data/query-plan-analyzer.php index ee056447a..ce9de7dbb 100644 --- a/tests/rules/data/query-plan-analyzer.php +++ b/tests/rules/data/query-plan-analyzer.php @@ -31,4 +31,12 @@ public function indexed(PDO $pdo, int $adaid): void { $pdo->query('SELECT * FROM `ada` WHERE adaid = '.$adaid); } + + 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); + } } From b4d461df951d923c49eccd115002c0d64857d4d4 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 24 May 2022 22:46:29 +0200 Subject: [PATCH 20/24] fix --- .phpstan-dba-pdo-mysql.cache | 6 +-- .../default/config/.phpstan-dba-mysqli.cache | 4 -- .../config/.phpstan-dba-pdo-mysql.cache | 4 ++ .../config/.phpunit-phpstan-dba-mysqli.cache | 4 ++ .../.phpunit-phpstan-dba-pdo-mysql.cache | 4 -- tests/rules/config/.phpstan-dba-mysqli.cache | 29 ---------- .../rules/config/.phpstan-dba-pdo-mysql.cache | 29 ++++++++++ .../config/.phpunit-phpstan-dba-mysqli.cache | 54 +++---------------- .../.phpunit-phpstan-dba-pdo-mysql.cache | 54 +++---------------- 9 files changed, 54 insertions(+), 134 deletions(-) diff --git a/.phpstan-dba-pdo-mysql.cache b/.phpstan-dba-pdo-mysql.cache index 5516075c0..c5544ecca 100644 --- a/.phpstan-dba-pdo-mysql.cache +++ b/.phpstan-dba-pdo-mysql.cache @@ -714,7 +714,7 @@ WHERE table_name = \'1970-01-01\'' => )), 2 => PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => true, + 'sortedTypes' => false, 'types' => array ( 0 => @@ -727,7 +727,7 @@ WHERE table_name = \'1970-01-01\'' => )), 3 => PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => true, + 'sortedTypes' => false, 'types' => array ( 0 => @@ -784,7 +784,7 @@ WHERE table_name = \'1970-01-01\'' => )), 'itemType' => PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => true, + 'sortedTypes' => false, 'types' => array ( 0 => diff --git a/tests/default/config/.phpstan-dba-mysqli.cache b/tests/default/config/.phpstan-dba-mysqli.cache index ab7cc79bb..8a36e3bca 100644 --- a/tests/default/config/.phpstan-dba-mysqli.cache +++ b/tests/default/config/.phpstan-dba-mysqli.cache @@ -3274,10 +3274,6 @@ FROM ada' => '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', 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/default/config/.phpstan-dba-pdo-mysql.cache b/tests/default/config/.phpstan-dba-pdo-mysql.cache index 620e34e6d..695a6ffc6 100644 --- a/tests/default/config/.phpstan-dba-pdo-mysql.cache +++ b/tests/default/config/.phpstan-dba-pdo-mysql.cache @@ -3274,6 +3274,10 @@ FROM ada' => 'message' => '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', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/default/config/.phpunit-phpstan-dba-mysqli.cache b/tests/default/config/.phpunit-phpstan-dba-mysqli.cache index 44fe9fd3a..95dd07083 100644 --- a/tests/default/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/default/config/.phpunit-phpstan-dba-mysqli.cache @@ -3394,6 +3394,10 @@ FROM ada' => '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', 'code' => 1064, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache b/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache index 3722c1430..9bb86605e 100644 --- a/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache +++ b/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache @@ -3274,10 +3274,6 @@ FROM ada' => 'message' => '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', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/rules/config/.phpstan-dba-mysqli.cache b/tests/rules/config/.phpstan-dba-mysqli.cache index 4d45fac36..df6755cf6 100644 --- a/tests/rules/config/.phpstan-dba-mysqli.cache +++ b/tests/rules/config/.phpstan-dba-mysqli.cache @@ -388,10 +388,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'group statement\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -400,10 +396,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -412,10 +404,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -577,10 +565,6 @@ 'message' => 'Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => 1146, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( @@ -832,10 +816,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'field list\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email FROM ada WHERE gesperrt=:gesperrt' => array ( @@ -908,11 +888,6 @@ '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', 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - 3 => NULL, - ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -1171,10 +1146,6 @@ '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, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( diff --git a/tests/rules/config/.phpstan-dba-pdo-mysql.cache b/tests/rules/config/.phpstan-dba-pdo-mysql.cache index 3d4f3e503..14bc15ad9 100644 --- a/tests/rules/config/.phpstan-dba-pdo-mysql.cache +++ b/tests/rules/config/.phpstan-dba-pdo-mysql.cache @@ -388,6 +388,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'group statement\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -396,6 +400,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'order clause\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -404,6 +412,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'where clause\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -565,6 +577,10 @@ 'message' => 'SQLSTATE[42S02]: Base table or view not found: 1146 Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => '42S02', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( @@ -816,6 +832,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'field list\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email FROM ada WHERE gesperrt=:gesperrt' => array ( @@ -888,6 +908,11 @@ 'message' => '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', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + 3 => NULL, + ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -1146,6 +1171,10 @@ 'message' => '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 \'FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( diff --git a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache index 5321a920a..672406cdb 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache @@ -77,7 +77,6 @@ ), 'SELECT * FROM `ada` WHERE adaid = 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -385,7 +384,6 @@ ), 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -544,10 +542,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'group statement\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -556,10 +550,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -568,13 +558,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -733,13 +720,10 @@ 'message' => 'Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => 1146, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -911,6 +895,10 @@ '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 WHERE LIMIT 0\' at line 1', 'code' => 1064, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT adaid FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -1017,10 +1005,6 @@ 'message' => 'Unknown column \'doesNotExist\' in \'field list\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email FROM ada WHERE adaid IN (\'1\')' => array ( @@ -1066,11 +1050,6 @@ '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', 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - 3 => NULL, - ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -1079,10 +1058,6 @@ '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', 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada @@ -1259,10 +1234,6 @@ 'message' => 'Unknown column \'xy\' in \'group statement\'', 'code' => 1054, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada WHERE adaid = \'1\'' => array ( @@ -1405,7 +1376,6 @@ ), 'SELECT email, adaid FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -1512,10 +1482,6 @@ '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, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( @@ -1526,7 +1492,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada' => array ( - 'error' => NULL, 'result' => array ( 3 => @@ -1787,7 +1752,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -1941,7 +1905,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -2282,11 +2245,6 @@ 'message' => 'Unknown column \'asdsa\' in \'where clause\'', 'code' => 1054, )), - 'result' => - array ( - 3 => NULL, - 5 => NULL, - ), ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE gesperrt=\'1\'' => array ( diff --git a/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache b/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache index 74ed8ae99..0f6491e9a 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache @@ -77,6 +77,7 @@ ), 'SELECT * FROM `ada` WHERE adaid = 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -230,6 +231,7 @@ ), 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -388,10 +390,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'group statement\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -400,10 +398,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'order clause\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -412,13 +406,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'where clause\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -577,13 +568,10 @@ 'message' => 'SQLSTATE[42S02]: Base table or view not found: 1146 Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => '42S02', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -755,6 +743,10 @@ 'message' => '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 \'FROM WHERE LIMIT 0\' at line 1', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT adaid FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -861,10 +853,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'field list\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email FROM ada WHERE adaid IN (\'1\')' => array ( @@ -910,11 +898,6 @@ 'message' => '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', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - 3 => NULL, - ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -923,10 +906,6 @@ 'message' => '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 \'gesperrt freigabe1u1 FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada @@ -1103,10 +1082,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'xy\' in \'group statement\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada WHERE adaid = \'1\'' => array ( @@ -1249,7 +1224,6 @@ ), 'SELECT email, adaid FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -1356,10 +1330,6 @@ 'message' => '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 \'FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( @@ -1370,7 +1340,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada' => array ( - 'error' => NULL, 'result' => array ( 3 => @@ -1631,7 +1600,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -1785,7 +1753,6 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -2126,11 +2093,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'asdsa\' in \'where clause\'', 'code' => '42S22', )), - 'result' => - array ( - 3 => NULL, - 5 => NULL, - ), ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE gesperrt=\'1\'' => array ( From e6501c74571f71df4fa520c0aba681900a08e29e Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Wed, 25 May 2022 14:34:41 +0200 Subject: [PATCH 21/24] prevent false-positives on small tables --- .phpstan-dba-mysqli.cache | 643 ++---------------- src/Analyzer/QueryPlanAnalyzerMysql.php | 26 +- src/Analyzer/QueryPlanResult.php | 22 +- src/QueryReflection/RuntimeConfiguration.php | 20 +- src/Rules/QueryPlanAnalyzerRule.php | 37 +- .../config/.phpunit-phpstan-dba-mysqli.cache | 4 - tests/rules/QueryPlanAnalyzerRuleTest.php | 22 +- .../config/.phpunit-phpstan-dba-mysqli.cache | 54 +- 8 files changed, 202 insertions(+), 626 deletions(-) diff --git a/.phpstan-dba-mysqli.cache b/.phpstan-dba-mysqli.cache index 99730a835..76180ccf2 100644 --- a/.phpstan-dba-mysqli.cache +++ b/.phpstan-dba-mysqli.cache @@ -1,6 +1,6 @@ 'v8-trim-queries', - 'schemaHash' => 'e7af3addf6476bf35bda4893b0b4e1e6', + 'schemaHash' => 'fc85743b94657f20850e7a591108f2c5', 'records' => array ( 'SELECT @@ -332,394 +332,11 @@ )), ), ), - '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 => - PHPStan\Type\Constant\ConstantArrayType::__set_state(array( - 'allArrays' => NULL, - 'nextAutoIndexes' => - array ( - 0 => 3, - ), - 'keyTypes' => - array ( - 0 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'COLUMN_NAME', - 'isClassString' => false, - )), - 1 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 0, - )), - 2 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'EXTRA', - 'isClassString' => false, - )), - 3 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 1, - )), - 4 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'COLUMN_TYPE', - 'isClassString' => false, - )), - 5 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 2, - )), - ), - 'valueTypes' => - array ( - 0 => - PHPStan\Type\StringType::__set_state(array( - )), - 1 => - PHPStan\Type\StringType::__set_state(array( - )), - 2 => - PHPStan\Type\StringType::__set_state(array( - )), - 3 => - PHPStan\Type\StringType::__set_state(array( - )), - 4 => - PHPStan\Type\StringType::__set_state(array( - )), - 5 => - PHPStan\Type\StringType::__set_state(array( - )), - ), - 'optionalKeys' => - array ( - ), - 'keyType' => - PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => true, - 'types' => - array ( - 0 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 0, - )), - 1 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 1, - )), - 2 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 2, - )), - 3 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'COLUMN_NAME', - 'isClassString' => false, - )), - 4 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'COLUMN_TYPE', - 'isClassString' => false, - )), - 5 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'EXTRA', - 'isClassString' => false, - )), - ), - )), - 'itemType' => - PHPStan\Type\StringType::__set_state(array( - )), - )), - ), - ), - 'SELECT - coalesce(COLUMN_NAME, "") as COLUMN_NAME, - coalesce(EXTRA, "") as EXTRA, - COLUMN_TYPE - FROM information_schema.columns - WHERE table_name = ? AND table_schema = DATABASE()' => - array ( - 'result' => - array ( - 5 => NULL, - ), - ), - 'SELECT - MD5( - GROUP_CONCAT( - CONCAT( - COALESCE(COLUMN_NAME, ""), - COALESCE(EXTRA, ""), - COLUMN_TYPE, - IS_NULLABLE - ) - ) - ) AS dbsignature, - 1 AS grouper - FROM - information_schema.columns - WHERE - table_schema = DATABASE() - GROUP BY - grouper' => - array ( - 'result' => - array ( - 5 => - PHPStan\Type\Constant\ConstantArrayType::__set_state(array( - 'allArrays' => NULL, - 'nextAutoIndexes' => - array ( - 0 => 2, - ), - 'keyTypes' => - array ( - 0 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'dbsignature', - 'isClassString' => false, - )), - 1 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 0, - )), - 2 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'grouper', - 'isClassString' => false, - )), - 3 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 1, - )), - ), - 'valueTypes' => - array ( - 0 => - PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => false, - 'types' => - array ( - 0 => - PHPStan\Type\StringType::__set_state(array( - )), - 1 => - PHPStan\Type\NullType::__set_state(array( - )), - ), - )), - 1 => - PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => false, - 'types' => - array ( - 0 => - PHPStan\Type\StringType::__set_state(array( - )), - 1 => - PHPStan\Type\NullType::__set_state(array( - )), - ), - )), - 2 => - PHPStan\Type\IntegerType::__set_state(array( - )), - 3 => - PHPStan\Type\IntegerType::__set_state(array( - )), - ), - 'optionalKeys' => - array ( - ), - 'keyType' => - PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => true, - 'types' => - array ( - 0 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 0, - )), - 1 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 1, - )), - 2 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'dbsignature', - 'isClassString' => false, - )), - 3 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'grouper', - 'isClassString' => false, - )), - ), - )), - 'itemType' => - PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => false, - 'types' => - array ( - 0 => - PHPStan\Type\StringType::__set_state(array( - )), - 1 => - PHPStan\Type\IntegerType::__set_state(array( - )), - 2 => - PHPStan\Type\NullType::__set_state(array( - )), - ), - )), - )), - 3 => - PHPStan\Type\Constant\ConstantArrayType::__set_state(array( - 'allArrays' => NULL, - 'nextAutoIndexes' => - array ( - 0 => 0, - ), - 'keyTypes' => - array ( - 0 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'dbsignature', - 'isClassString' => false, - )), - 1 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'grouper', - 'isClassString' => false, - )), - ), - 'valueTypes' => - array ( - 0 => - PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => false, - 'types' => - array ( - 0 => - PHPStan\Type\StringType::__set_state(array( - )), - 1 => - PHPStan\Type\NullType::__set_state(array( - )), - ), - )), - 1 => - PHPStan\Type\IntegerType::__set_state(array( - )), - ), - 'optionalKeys' => - array ( - ), - 'keyType' => - PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => true, - 'types' => - array ( - 0 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'dbsignature', - 'isClassString' => false, - )), - 1 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'grouper', - 'isClassString' => false, - )), - ), - )), - 'itemType' => - PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => false, - 'types' => - array ( - 0 => - PHPStan\Type\StringType::__set_state(array( - )), - 1 => - PHPStan\Type\IntegerType::__set_state(array( - )), - 2 => - PHPStan\Type\NullType::__set_state(array( - )), - ), - )), - )), - ), - ), 'SELECT * FROM `ada` WHERE adaid = 1' => array ( 'error' => NULL, ), 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => - array ( - 'error' => NULL, - ), - 'SELECT adaid FROM ada LIMIT 1 FOR SHARE' => - array ( - 'error' => NULL, - ), - 'SELECT adaid FROM ada LIMIT 1 FOR SHARE NOWAIT' => - array ( - 'error' => NULL, - ), - 'SELECT adaid FROM ada LIMIT 1 FOR SHARE SKIP LOCKED' => - array ( - 'error' => NULL, - ), - 'SELECT adaid FROM ada LIMIT 1 FOR UPDATE NOWAIT' => - array ( - 'error' => NULL, - ), - 'SELECT adaid FROM ada LIMIT 1 FOR UPDATE SKIP LOCKED' => - array ( - 'error' => NULL, - ), - 'SELECT adaid FROM ada LIMIT 1 OFFSET 1' => - array ( - 'error' => NULL, - ), - 'SELECT adaid FROM ada LIMIT 1 OFFSET 1 FOR UPDATE' => - array ( - 'error' => NULL, - ), - 'SELECT adaid FROM ada WHERE email LIKE \'%questions ?%\'' => - array ( - 'error' => NULL, - ), - 'SELECT adaid FROM ada WHERE email LIKE \':gesperrt%\'' => - array ( - 'error' => NULL, - ), - 'SELECT adaid FROM ada WHERE email LIKE \'hello?%\'' => - array ( - 'error' => NULL, - ), - 'SELECT akid FROM ak WHERE eadavk>1.0' => - array ( - 'error' => NULL, - ), - 'SELECT akid FROM ak WHERE eadavk>1.1' => - array ( - 'error' => NULL, - ), - 'SELECT column_name, column_default, is_nullable -FROM information_schema.columns -WHERE table_name = \'1970-01-01\'' => array ( 'result' => array ( @@ -728,13 +345,13 @@ WHERE table_name = \'1970-01-01\'' => 'allArrays' => NULL, 'nextAutoIndexes' => array ( - 0 => 3, + 0 => 4, ), 'keyTypes' => array ( 0 => PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'COLUMN_NAME', + 'value' => 'adaid', 'isClassString' => false, )), 1 => @@ -743,7 +360,7 @@ WHERE table_name = \'1970-01-01\'' => )), 2 => PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'COLUMN_DEFAULT', + 'value' => 'gesperrt', 'isClassString' => false, )), 3 => @@ -752,47 +369,44 @@ WHERE table_name = \'1970-01-01\'' => )), 4 => PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'IS_NULLABLE', + 'value' => 'email', 'isClassString' => false, )), 5 => PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( 'value' => 2, )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, + )), ), 'valueTypes' => array ( 0 => - PHPStan\Type\StringType::__set_state(array( + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, )), 1 => - PHPStan\Type\StringType::__set_state(array( + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, )), 2 => - PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => false, - 'types' => - array ( - 0 => - PHPStan\Type\StringType::__set_state(array( - )), - 1 => - PHPStan\Type\NullType::__set_state(array( - )), - ), + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, )), 3 => - PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => false, - 'types' => - array ( - 0 => - PHPStan\Type\StringType::__set_state(array( - )), - 1 => - PHPStan\Type\NullType::__set_state(array( - )), - ), + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, )), 4 => PHPStan\Type\StringType::__set_state(array( @@ -800,6 +414,16 @@ WHERE table_name = \'1970-01-01\'' => 5 => PHPStan\Type\StringType::__set_state(array( )), + 6 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), + 7 => + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -128, + 'max' => 127, + )), ), 'optionalKeys' => array ( @@ -822,18 +446,27 @@ WHERE table_name = \'1970-01-01\'' => 'value' => 2, )), 3 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'COLUMN_DEFAULT', - 'isClassString' => false, + PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( + 'value' => 3, )), 4 => PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'COLUMN_NAME', + 'value' => 'adaid', 'isClassString' => false, )), 5 => PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'IS_NULLABLE', + 'value' => 'email', + 'isClassString' => false, + )), + 6 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'freigabe1u1', + 'isClassString' => false, + )), + 7 => + PHPStan\Type\Constant\ConstantStringType::__set_state(array( + 'value' => 'gesperrt', 'isClassString' => false, )), ), @@ -844,10 +477,12 @@ WHERE table_name = \'1970-01-01\'' => 'types' => array ( 0 => - PHPStan\Type\StringType::__set_state(array( + PHPStan\Type\IntegerRangeType::__set_state(array( + 'min' => -32768, + 'max' => 32767, )), 1 => - PHPStan\Type\NullType::__set_state(array( + PHPStan\Type\StringType::__set_state(array( )), ), )), @@ -856,15 +491,6 @@ WHERE table_name = \'1970-01-01\'' => ), 'SELECT column_name, column_default, is_nullable FROM information_schema.columns -WHERE table_name = ?' => - array ( - 'result' => - array ( - 5 => NULL, - ), - ), - 'SELECT column_name, column_default, is_nullable -FROM information_schema.columns WHERE table_name = \'1970-01-01\'' => array ( 'result' => @@ -1009,167 +635,6 @@ WHERE table_name = ?' => 5 => NULL, ), ), - 'SELECT eladaid FROM ak' => - array ( - 'error' => NULL, - ), - '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', - 'code' => 1064, - )), - ), - 'SELECT email, adaid FROM ada' => - array ( - 'result' => - array ( - 5 => - PHPStan\Type\Constant\ConstantArrayType::__set_state(array( - 'allArrays' => NULL, - 'nextAutoIndexes' => - array ( - 0 => 2, - ), - 'keyTypes' => - array ( - 0 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'email', - 'isClassString' => false, - )), - 1 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 0, - )), - 2 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'adaid', - 'isClassString' => false, - )), - 3 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 1, - )), - ), - 'valueTypes' => - array ( - 0 => - PHPStan\Type\StringType::__set_state(array( - )), - 1 => - PHPStan\Type\StringType::__set_state(array( - )), - 2 => - PHPStan\Type\IntegerRangeType::__set_state(array( - 'min' => -32768, - 'max' => 32767, - )), - 3 => - PHPStan\Type\IntegerRangeType::__set_state(array( - 'min' => -32768, - 'max' => 32767, - )), - ), - 'optionalKeys' => - array ( - ), - 'keyType' => - PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => true, - 'types' => - array ( - 0 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 0, - )), - 1 => - PHPStan\Type\Constant\ConstantIntegerType::__set_state(array( - 'value' => 1, - )), - 2 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'adaid', - 'isClassString' => false, - )), - 3 => - PHPStan\Type\Constant\ConstantStringType::__set_state(array( - 'value' => 'email', - 'isClassString' => false, - )), - ), - )), - 'itemType' => - PHPStan\Type\UnionType::__set_state(array( - 'sortedTypes' => false, - 'types' => - array ( - 0 => - PHPStan\Type\StringType::__set_state(array( - )), - 1 => - PHPStan\Type\IntegerRangeType::__set_state(array( - 'min' => -32768, - 'max' => 32767, - )), - ), - )), - )), - ), - ), - 'SELECT email, adaid FROM ada LIMIT 1' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid FROM ada LIMIT 1, 10' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid FROM ada WHERE adaid = 1' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid FROM ada WHERE adaid = 2' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid FROM ada WHERE adaid = 3' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid FROM ada WHERE adaid IN(1,3)' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid FROM ada WHERE adaid=' => - 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 \'LIMIT 0\' at line 1', - 'code' => 1064, - )), - ), - 'SELECT email, adaid FROM ada WHERE adaid=1' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid FROM ada WHERE email = \'test@example.org\'' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid FROM ada WHERE email = \'webmaster@example.org\'' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid FROM ada WHERE email=\'foo\'' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid FROM ada WHERE gesperrt = \'1\'' => - array ( - 'error' => NULL, - ), ), 'runtimeConfig' => array ( diff --git a/src/Analyzer/QueryPlanAnalyzerMysql.php b/src/Analyzer/QueryPlanAnalyzerMysql.php index 9edbf91cc..5bbdb0b10 100644 --- a/src/Analyzer/QueryPlanAnalyzerMysql.php +++ b/src/Analyzer/QueryPlanAnalyzerMysql.php @@ -15,6 +15,10 @@ final class QueryPlanAnalyzerMysql * number of unindexed reads allowed before a query is considered inefficient. */ public const DEFAULT_UNINDEXED_READS_THRESHOLD = 100000; + /** + * max number of rows in a table, for which we don't report errors, because using a index/table-scan wouldn't improve performance. + */ + public const DEFAULT_SMALL_TABLE_THRESHOLD = 1000; /** * @var PDO|mysqli @@ -50,31 +54,37 @@ public function analyze(string $query): QueryPlanResult } /** - * @param \IteratorAggregate $it + * @param \IteratorAggregate $it */ private function buildResult($it): QueryPlanResult { $result = new QueryPlanResult(); - $allowedUnindexedReads = QueryReflection::getRuntimeConfiguration()->getNumberOfAllowedUnindexedReads(); + $allowedUnindexedReads = QueryReflection::getRuntimeConfiguration()->getNumberOfAllowedUnindexedReads(); if (false === $allowedUnindexedReads) { throw new ShouldNotHappenException(); } + $allowedRowsNotRequiringIndex = QueryReflection::getRuntimeConfiguration()->getNumberOfRowsNotRequiringIndex(); + if (false === $allowedRowsNotRequiringIndex) { + throw new ShouldNotHappenException(); + } + foreach ($it as $row) { // we cannot analyse tables without rows -> mysql will just return 'no matching row in const table' if (null === $row['table']) { continue; } - if (null === $row['key']) { + if (null === $row['key'] && $row['rows'] > $allowedRowsNotRequiringIndex) { $result->addRow($row['table'], QueryPlanResult::NO_INDEX); } else { - if (true === $allowedUnindexedReads && $row['rows'] > self::DEFAULT_UNINDEXED_READS_THRESHOLD) { - $result->addRow($row['table'], QueryPlanResult::NOT_EFFICIENT); - } - if (\is_int($allowedUnindexedReads) && $row['rows'] > $allowedUnindexedReads) { - $result->addRow($row['table'], QueryPlanResult::NOT_EFFICIENT); + if (null !== $row['type'] && 'all' === strtolower($row['type']) && $row['rows'] > $allowedRowsNotRequiringIndex) { + $result->addRow($row['table'], QueryPlanResult::TABLE_SCAN); + } elseif (true === $allowedUnindexedReads && $row['rows'] > self::DEFAULT_UNINDEXED_READS_THRESHOLD) { + $result->addRow($row['table'], QueryPlanResult::UNINDEXED_READS); + } elseif (\is_int($allowedUnindexedReads) && $row['rows'] > $allowedUnindexedReads) { + $result->addRow($row['table'], QueryPlanResult::UNINDEXED_READS); } } } diff --git a/src/Analyzer/QueryPlanResult.php b/src/Analyzer/QueryPlanResult.php index 140ddb80b..d49943a7a 100644 --- a/src/Analyzer/QueryPlanResult.php +++ b/src/Analyzer/QueryPlanResult.php @@ -7,7 +7,8 @@ final class QueryPlanResult { public const NO_INDEX = 'no-index'; - public const NOT_EFFICIENT = 'inefficient'; + public const TABLE_SCAN = 'table-scan'; + public const UNINDEXED_READS = 'unindexed-reads'; /** * @var array @@ -42,11 +43,26 @@ public function getTablesNotUsingIndex(): array /** * @return string[] */ - public function getTablesNotEfficient(): array + public function getTablesDoingTableScan(): array { $tables = []; foreach ($this->result as $table => $result) { - if (self::NOT_EFFICIENT === $result) { + if (self::TABLE_SCAN === $result) { + $tables[] = $table; + } + } + + return $tables; + } + + /** + * @return string[] + */ + public function getTablesDoingUnindexedReads(): array + { + $tables = []; + foreach ($this->result as $table => $result) { + if (self::UNINDEXED_READS === $result) { $tables[] = $table; } } diff --git a/src/QueryReflection/RuntimeConfiguration.php b/src/QueryReflection/RuntimeConfiguration.php index 16cacb679..ba0ac01e2 100644 --- a/src/QueryReflection/RuntimeConfiguration.php +++ b/src/QueryReflection/RuntimeConfiguration.php @@ -44,6 +44,10 @@ final class RuntimeConfiguration * @var bool|0|positive-int */ private $numberOfAllowedUnindexedReads = false; + /** + * @var false|positive-int + */ + private $numberOfRowsNotRequiringIndex = false; public static function create(): self { @@ -105,15 +109,17 @@ public function stringifyTypes(bool $stringify): self * * Requires a active database connection. * - * @param bool|0|positive-int $numberOfAllowedUnindexedReads `true` to enable analysis. `false` to disable analysis. - * Otherwise the number of reads a query is allowed to execute, before it is considered inefficient, see QueryPlanAnalyzerMysql::DEFAULT_UNINDEXED_READS_THRESHOLD. + * @param bool|0|positive-int $numberOfAllowedUnindexedReads `true` to enable analysis with QueryPlanAnalyzerMysql::DEFAULT_UNINDEXED_READS_THRESHOLD. `false` to disable analysis. + * Otherwise the number of reads a query is allowed to execute, before it is considered inefficient. * `0` disables the efficiency checks but still scans for queries not using an index. + * @param positive-int $numberOfRowsNotRequiringIndex number of reads a query is allowed to execute, without requiring a index * * @return $this */ - public function analyzeQueryPlans($numberOfAllowedUnindexedReads = true): self + public function analyzeQueryPlans($numberOfAllowedUnindexedReads = true, $numberOfRowsNotRequiringIndex = QueryPlanAnalyzerMysql::DEFAULT_SMALL_TABLE_THRESHOLD): self { $this->numberOfAllowedUnindexedReads = $numberOfAllowedUnindexedReads; + $this->numberOfRowsNotRequiringIndex = $numberOfRowsNotRequiringIndex; return $this; } @@ -126,6 +132,14 @@ public function getNumberOfAllowedUnindexedReads() return $this->numberOfAllowedUnindexedReads; } + /** + * @return false|positive-int + */ + public function getNumberOfRowsNotRequiringIndex() + { + return $this->numberOfRowsNotRequiringIndex; + } + public function isDebugEnabled(): bool { return $this->debugMode; diff --git a/src/Rules/QueryPlanAnalyzerRule.php b/src/Rules/QueryPlanAnalyzerRule.php index eeded095c..8d94798e2 100644 --- a/src/Rules/QueryPlanAnalyzerRule.php +++ b/src/Rules/QueryPlanAnalyzerRule.php @@ -118,24 +118,43 @@ private function analyze(CallLike $callLike, Scope $scope): array $parameterTypes = $scope->getType($args[1]->value); } - $errors = []; + $ruleErrors = []; $queryReflection = new QueryReflection(); + $proposal = "\n\nConsider optimizing the query.\nIn some cases this is not a problem and this error should be ignored."; foreach ($queryReflection->analyzeQueryPlan($scope, $queryExpr, $parameterTypes) as $queryPlanResult) { $notUsingIndex = $queryPlanResult->getTablesNotUsingIndex(); if (\count($notUsingIndex) > 0) { foreach ($notUsingIndex as $table) { - $errors[] = sprintf('Query plan analyzer: table "%s" is not using an index', $table); + $ruleErrors[] = RuleErrorBuilder::message( + sprintf( + "Query is not using an index on table '%s'.".$proposal, + $table + )) + ->line($callLike->getLine()) + ->build(); } } else { - foreach ($queryPlanResult->getTablesNotEfficient() as $table) { - $errors[] = sprintf('Query plan analyzer: inefficient index use in table "%s"', $table); + foreach ($queryPlanResult->getTablesDoingTableScan() as $table) { + $ruleErrors[] = RuleErrorBuilder::message( + sprintf( + "Query is using a full-table-scan on table '%s'.".$proposal, + $table + )) + ->line($callLike->getLine()) + ->tip('see Mysql Docs https://dev.mysql.com/doc/refman/8.0/en/table-scan-avoidance.html') + ->build(); } - } - } - $ruleErrors = []; - foreach ($errors as $error) { - $ruleErrors[] = RuleErrorBuilder::message($error)->line($callLike->getLine())->build(); + foreach ($queryPlanResult->getTablesDoingUnindexedReads() as $table) { + $ruleErrors[] = RuleErrorBuilder::message( + sprintf( + "Query is triggering too many unindexed-reads on table '%s'.".$proposal, + $table + )) + ->line($callLike->getLine()) + ->build(); + } + } } return $ruleErrors; diff --git a/tests/default/config/.phpunit-phpstan-dba-mysqli.cache b/tests/default/config/.phpunit-phpstan-dba-mysqli.cache index 95dd07083..44fe9fd3a 100644 --- a/tests/default/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/default/config/.phpunit-phpstan-dba-mysqli.cache @@ -3394,10 +3394,6 @@ FROM ada' => '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', 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/rules/QueryPlanAnalyzerRuleTest.php b/tests/rules/QueryPlanAnalyzerRuleTest.php index 480292f6d..0d7471da8 100644 --- a/tests/rules/QueryPlanAnalyzerRuleTest.php +++ b/tests/rules/QueryPlanAnalyzerRuleTest.php @@ -16,6 +16,10 @@ class QueryPlanAnalyzerRuleTest extends RuleTestCase * @var bool|0|positive-int */ private $numberOfAllowedUnindexedReads; + /** + * @var positive-int + */ + private $numberOfRowsNotRequiringIndex; protected function tearDown(): void { @@ -24,7 +28,7 @@ protected function tearDown(): void protected function getRule(): Rule { - QueryReflection::getRuntimeConfiguration()->analyzeQueryPlans($this->numberOfAllowedUnindexedReads); + QueryReflection::getRuntimeConfiguration()->analyzeQueryPlans($this->numberOfAllowedUnindexedReads, $this->numberOfRowsNotRequiringIndex); return self::getContainer()->getByType(QueryPlanAnalyzerRule::class); } @@ -47,18 +51,28 @@ public function testNotUsingIndex(): void } $this->numberOfAllowedUnindexedReads = true; + $this->numberOfRowsNotRequiringIndex = 2; $this->analyse([__DIR__.'/data/query-plan-analyzer.php'], [ [ - 'Query plan analyzer: table "ada" is not using an index', + "Query is not using an index on table 'ada'. + +Consider optimizing the query. +In some cases this is not a problem and this error should be ignored.", 12, ], [ - 'Query plan analyzer: table "ada" is not using an index', + "Query is not using an index on table 'ada'. + +Consider optimizing the query. +In some cases this is not a problem and this error should be ignored.", 17, ], [ - 'Query plan analyzer: table "ada" is not using an index', + "Query is not using an index on table 'ada'. + +Consider optimizing the query. +In some cases this is not a problem and this error should be ignored.", 22, ], ]); diff --git a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache index 672406cdb..5321a920a 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-mysqli.cache @@ -77,6 +77,7 @@ ), 'SELECT * FROM `ada` WHERE adaid = 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -384,6 +385,7 @@ ), 'SELECT * FROM `ada` WHERE email = \'test@example.com\';' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -542,6 +544,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'group statement\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -550,6 +556,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -558,10 +568,13 @@ 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -720,10 +733,13 @@ 'message' => 'Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => 1146, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( - 'error' => NULL, 'result' => array ( 5 => @@ -895,10 +911,6 @@ '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 WHERE LIMIT 0\' at line 1', 'code' => 1064, )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT adaid FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -1005,6 +1017,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'field list\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email FROM ada WHERE adaid IN (\'1\')' => array ( @@ -1050,6 +1066,11 @@ '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', 'code' => 1064, )), + 'result' => + array ( + 5 => NULL, + 3 => NULL, + ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -1058,6 +1079,10 @@ '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', 'code' => 1064, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada @@ -1234,6 +1259,10 @@ 'message' => 'Unknown column \'xy\' in \'group statement\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada WHERE adaid = \'1\'' => array ( @@ -1376,6 +1405,7 @@ ), 'SELECT email, adaid FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -1482,6 +1512,10 @@ '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, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( @@ -1492,6 +1526,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada' => array ( + 'error' => NULL, 'result' => array ( 3 => @@ -1752,6 +1787,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -1905,6 +1941,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -2245,6 +2282,11 @@ 'message' => 'Unknown column \'asdsa\' in \'where clause\'', 'code' => 1054, )), + 'result' => + array ( + 3 => NULL, + 5 => NULL, + ), ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE gesperrt=\'1\'' => array ( From 3735445684561267b7291d45b8aaac2419d00fe4 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Wed, 25 May 2022 15:01:11 +0200 Subject: [PATCH 22/24] record --- .phpstan-dba-mysqli.cache | 88 +++++++++ .../default/config/.phpstan-dba-mysqli.cache | 4 + .../config/.phpstan-dba-pdo-mysql.cache | 4 - .../.phpunit-phpstan-dba-pdo-mysql.cache | 4 + tests/rules/config/.phpstan-dba-mysqli.cache | 29 +++ .../rules/config/.phpstan-dba-pdo-mysql.cache | 29 --- .../.phpunit-phpstan-dba-pdo-mysql.cache | 182 +++++------------- 7 files changed, 171 insertions(+), 169 deletions(-) diff --git a/.phpstan-dba-mysqli.cache b/.phpstan-dba-mysqli.cache index 76180ccf2..8522d1a72 100644 --- a/.phpstan-dba-mysqli.cache +++ b/.phpstan-dba-mysqli.cache @@ -489,6 +489,38 @@ )), ), ), + 'SELECT * FROM ada GROUP BY doesNotExist' => + array ( + 'error' => + staabm\PHPStanDba\Error::__set_state(array( + 'message' => 'Unknown column \'doesNotExist\' in \'group statement\'', + 'code' => 1054, + )), + ), + 'SELECT * FROM ada ORDER BY doesNotExist' => + array ( + 'error' => + staabm\PHPStanDba\Error::__set_state(array( + 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', + 'code' => 1054, + )), + ), + 'SELECT * FROM ada WHERE doesNotExist=1' => + array ( + 'error' => + staabm\PHPStanDba\Error::__set_state(array( + 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', + 'code' => 1054, + )), + ), + 'SELECT * FROM unknown_table' => + array ( + 'error' => + staabm\PHPStanDba\Error::__set_state(array( + 'message' => 'Table \'phpstan_dba.unknown_table\' doesn\'t exist', + 'code' => 1146, + )), + ), 'SELECT column_name, column_default, is_nullable FROM information_schema.columns WHERE table_name = \'1970-01-01\'' => @@ -635,6 +667,62 @@ WHERE table_name = ?' => 5 => NULL, ), ), + 'SELECT doesNotExist, adaid, gesperrt, freigabe1u1 FROM ada' => + array ( + 'error' => + staabm\PHPStanDba\Error::__set_state(array( + 'message' => 'Unknown column \'doesNotExist\' in \'field list\'', + 'code' => 1054, + )), + ), + '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', + 'code' => 1064, + )), + ), + 'SELECT email, adaid FROM ada GROUP BY xy LIMIT 1' => + array ( + 'error' => + staabm\PHPStanDba\Error::__set_state(array( + 'message' => 'Unknown column \'xy\' in \'group statement\'', + 'code' => 1054, + )), + ), + 'SELECT email, adaid FROM ada WHERE email=\'my_other_table\' LIMIT 1' => + array ( + 'error' => NULL, + ), + '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 ( + 'error' => NULL, + ), + 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada LIMIT 1' => + array ( + 'error' => NULL, + ), + 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE email=\'my_other_table\' LIMIT 1' => + array ( + 'error' => NULL, + ), + '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, + )), + ), ), 'runtimeConfig' => array ( diff --git a/tests/default/config/.phpstan-dba-mysqli.cache b/tests/default/config/.phpstan-dba-mysqli.cache index 8a36e3bca..ab7cc79bb 100644 --- a/tests/default/config/.phpstan-dba-mysqli.cache +++ b/tests/default/config/.phpstan-dba-mysqli.cache @@ -3274,6 +3274,10 @@ FROM ada' => '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', 'code' => 1064, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/default/config/.phpstan-dba-pdo-mysql.cache b/tests/default/config/.phpstan-dba-pdo-mysql.cache index 695a6ffc6..620e34e6d 100644 --- a/tests/default/config/.phpstan-dba-pdo-mysql.cache +++ b/tests/default/config/.phpstan-dba-pdo-mysql.cache @@ -3274,10 +3274,6 @@ FROM ada' => 'message' => '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', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache b/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache index 9bb86605e..3722c1430 100644 --- a/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache +++ b/tests/default/config/.phpunit-phpstan-dba-pdo-mysql.cache @@ -3274,6 +3274,10 @@ FROM ada' => 'message' => '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', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada' => array ( diff --git a/tests/rules/config/.phpstan-dba-mysqli.cache b/tests/rules/config/.phpstan-dba-mysqli.cache index df6755cf6..4d45fac36 100644 --- a/tests/rules/config/.phpstan-dba-mysqli.cache +++ b/tests/rules/config/.phpstan-dba-mysqli.cache @@ -388,6 +388,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'group statement\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -396,6 +400,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'order clause\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -404,6 +412,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'where clause\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -565,6 +577,10 @@ 'message' => 'Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => 1146, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( @@ -816,6 +832,10 @@ 'message' => 'Unknown column \'doesNotExist\' in \'field list\'', 'code' => 1054, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email FROM ada WHERE gesperrt=:gesperrt' => array ( @@ -888,6 +908,11 @@ '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', 'code' => 1064, )), + 'result' => + array ( + 5 => NULL, + 3 => NULL, + ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -1146,6 +1171,10 @@ '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, )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( diff --git a/tests/rules/config/.phpstan-dba-pdo-mysql.cache b/tests/rules/config/.phpstan-dba-pdo-mysql.cache index 14bc15ad9..3d4f3e503 100644 --- a/tests/rules/config/.phpstan-dba-pdo-mysql.cache +++ b/tests/rules/config/.phpstan-dba-pdo-mysql.cache @@ -388,10 +388,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'group statement\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -400,10 +396,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'order clause\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -412,10 +404,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'where clause\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -577,10 +565,6 @@ 'message' => 'SQLSTATE[42S02]: Base table or view not found: 1146 Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => '42S02', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( @@ -832,10 +816,6 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'field list\'', 'code' => '42S22', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email FROM ada WHERE gesperrt=:gesperrt' => array ( @@ -908,11 +888,6 @@ 'message' => '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', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - 3 => NULL, - ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -1171,10 +1146,6 @@ 'message' => '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 \'FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), - 'result' => - array ( - 5 => NULL, - ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( diff --git a/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache b/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache index 0f6491e9a..f6b483443 100644 --- a/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache +++ b/tests/rules/config/.phpunit-phpstan-dba-pdo-mysql.cache @@ -3,42 +3,6 @@ 'schemaHash' => NULL, 'records' => array ( - 'SELECT - ada.*, - COALESCE(NULLIF(email, ""), email) AS email - FROM ada - INNER JOIN ak ON (ak.adaid = ada.adaid AND ak.akid = \'1\') - WHERE adaid = 1 ORDER BY COALESCE(NULLIF(email, ""), email) ASC' => - array ( - 'result' => - array ( - 5 => NULL, - ), - ), - 'SELECT - ada.*, - COALESCE(NULLIF(email, ""), email) AS email - FROM ada - INNER JOIN ak ON (ak.adaid = ada.adaid AND ak.akid = :akid) - WHERE adaid = 1 ORDER BY COALESCE(NULLIF(email, ""), email) ASC' => - array ( - 'result' => - array ( - 5 => NULL, - ), - ), - 'SELECT - ada.*, - COALESCE(NULLIF(email, ""), email) AS email - FROM ada - INNER JOIN ak ON (ak.adaid = ada.adaid AND ak.akid = ?) - WHERE adaid = 1 ORDER BY COALESCE(NULLIF(email, ""), email) ASC' => - array ( - 'result' => - array ( - 5 => NULL, - ), - ), 'SELECT ada.*, COALESCE(NULLIF(email, ""), email) AS email @@ -390,6 +354,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'group statement\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada ORDER BY doesNotExist' => array ( @@ -398,6 +366,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'order clause\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE doesNotExist=1' => array ( @@ -406,6 +378,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'where clause\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT * FROM ada WHERE email = \'1970-01-01\'' => array ( @@ -568,6 +544,10 @@ 'message' => 'SQLSTATE[42S02]: Base table or view not found: 1146 Table \'phpstan_dba.unknown_table\' doesn\'t exist', 'code' => '42S02', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT *,adaid FROM `ada` WHERE email = \'test@example.com\';' => array ( @@ -853,6 +833,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'doesNotExist\' in \'field list\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email FROM ada WHERE adaid IN (\'1\')' => array ( @@ -880,17 +864,6 @@ 'code' => '42000', )), ), - 'SELECT email adaid - WHERE gesperrt = \'1\' AND email LIKE \'%@example.com\' - FROM ada - LIMIT 1' => - array ( - 'error' => - staabm\PHPStanDba\Error::__set_state(array( - 'message' => '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 \'FROM ada LIMIT 0\' at line 3', - 'code' => '42000', - )), - ), 'SELECT email adaid WHERE gesperrt freigabe1u1 FROM ada' => array ( 'error' => @@ -898,6 +871,11 @@ 'message' => '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', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + 3 => NULL, + ), ), 'SELECT email adaid gesperrt freigabe1u1 FROM ada' => array ( @@ -906,90 +884,10 @@ 'message' => '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 \'gesperrt freigabe1u1 FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), - ), - 'SELECT email, adaid - FROM ada - WHERE gesperrt = \'1\' - FOR UPDATE' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid - FROM ada - WHERE gesperrt = \'1\' - LIMIT \'1\'' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid - FROM ada - WHERE gesperrt = \'1\' - LIMIT \'1\' - FOR UPDATE' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid - FROM ada - WHERE gesperrt = \'1\' - LIMIT \'1\' - OFFSET \'1\'' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid - FROM ada - WHERE gesperrt = \'1\' - LIMIT \'1\' - OFFSET \'1\' - FOR SHARE' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid - FROM ada - WHERE gesperrt = \'1\' - LIMIT \'1\' - OFFSET \'1\' - FOR UPDATE' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid - FROM ada - WHERE gesperrt = \'1\' - LIMIT \'1\' - OFFSET 1' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid - FROM ada - WHERE gesperrt = \'1\' - LIMIT \'1\', \'1\'' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid - FROM ada - WHERE gesperrt = \'1\' - LIMIT \'1\', \'1\'' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid - FROM ada - WHERE gesperrt = \'1\' AND email LIKE \'%@example%\' - LIMIT 1' => - array ( - 'error' => NULL, - ), - 'SELECT email, adaid - FROM ada - WHERE gesperrt = \'1\' AND email LIKE NULL - LIMIT 1' => - array ( - 'error' => NULL, + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada @@ -1082,6 +980,10 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'xy\' in \'group statement\'', 'code' => '42S22', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid FROM ada WHERE adaid = \'1\'' => array ( @@ -1224,6 +1126,7 @@ ), 'SELECT email, adaid FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -1330,6 +1233,10 @@ 'message' => '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 \'FROM ada LIMIT 0\' at line 1', 'code' => '42000', )), + 'result' => + array ( + 5 => NULL, + ), ), 'SELECT email, adaid GROUP BY xy FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( @@ -1340,6 +1247,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada' => array ( + 'error' => NULL, 'result' => array ( 3 => @@ -1593,13 +1501,9 @@ array ( 'error' => NULL, ), - 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada - WHERE (gesperrt=\'1\' AND freigabe1u1=1) OR (gesperrt=\'1\' AND freigabe1u1=0)' => - array ( - 'error' => NULL, - ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -1753,6 +1657,7 @@ ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE email=\'my_other_table\' LIMIT 1' => array ( + 'error' => NULL, 'result' => array ( 5 => @@ -2093,6 +1998,11 @@ 'message' => 'SQLSTATE[42S22]: Column not found: 1054 Unknown column \'asdsa\' in \'where clause\'', 'code' => '42S22', )), + 'result' => + array ( + 3 => NULL, + 5 => NULL, + ), ), 'SELECT email, adaid, gesperrt, freigabe1u1 FROM ada WHERE gesperrt=\'1\'' => array ( From 57665c9d29d74f4d9d5fbd93a96a451e87a39641 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Wed, 25 May 2022 15:11:54 +0200 Subject: [PATCH 23/24] ignore derived tables --- src/Analyzer/QueryPlanAnalyzerMysql.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Analyzer/QueryPlanAnalyzerMysql.php b/src/Analyzer/QueryPlanAnalyzerMysql.php index 5bbdb0b10..9008e5679 100644 --- a/src/Analyzer/QueryPlanAnalyzerMysql.php +++ b/src/Analyzer/QueryPlanAnalyzerMysql.php @@ -54,7 +54,7 @@ public function analyze(string $query): QueryPlanResult } /** - * @param \IteratorAggregate $it + * @param \IteratorAggregate $it */ private function buildResult($it): QueryPlanResult { @@ -77,6 +77,12 @@ private function buildResult($it): QueryPlanResult } if (null === $row['key'] && $row['rows'] > $allowedRowsNotRequiringIndex) { + // derived table aka. a expression that generates a table within the scope of a query FROM clause + // is a temporary table, which indexes cannot be created for. + if (strtolower($row['select_type']) === 'derived') { + continue; + } + $result->addRow($row['table'], QueryPlanResult::NO_INDEX); } else { if (null !== $row['type'] && 'all' === strtolower($row['type']) && $row['rows'] > $allowedRowsNotRequiringIndex) { From 08d9d4ed71aa2e6250dbb6c077f892bbca8ecd73 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Wed, 25 May 2022 15:17:07 +0200 Subject: [PATCH 24/24] cs --- src/Analyzer/QueryPlanAnalyzerMysql.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Analyzer/QueryPlanAnalyzerMysql.php b/src/Analyzer/QueryPlanAnalyzerMysql.php index 9008e5679..ace7d6e40 100644 --- a/src/Analyzer/QueryPlanAnalyzerMysql.php +++ b/src/Analyzer/QueryPlanAnalyzerMysql.php @@ -79,7 +79,7 @@ private function buildResult($it): QueryPlanResult if (null === $row['key'] && $row['rows'] > $allowedRowsNotRequiringIndex) { // derived table aka. a expression that generates a table within the scope of a query FROM clause // is a temporary table, which indexes cannot be created for. - if (strtolower($row['select_type']) === 'derived') { + if ('derived' === strtolower($row['select_type'])) { continue; }