diff --git a/src/DbaException.php b/src/DbaException.php index ec7377cc3..f5ec678f3 100644 --- a/src/DbaException.php +++ b/src/DbaException.php @@ -2,6 +2,6 @@ namespace staabm\PHPStanDba; -final class DbaException extends \Exception +final class DbaException extends \RuntimeException { } diff --git a/src/Extensions/DeployerRunMysqlQueryDynamicReturnTypeExtension.php b/src/Extensions/DeployerRunMysqlQueryDynamicReturnTypeExtension.php index 51c9750ab..ddb14a752 100644 --- a/src/Extensions/DeployerRunMysqlQueryDynamicReturnTypeExtension.php +++ b/src/Extensions/DeployerRunMysqlQueryDynamicReturnTypeExtension.php @@ -35,7 +35,12 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, } $queryReflection = new QueryReflection(); - $resultType = $queryReflection->getResultType($args[0]->value, $scope, QueryReflector::FETCH_TYPE_NUMERIC); + $queryString = $queryReflection->resolveQueryString($args[0]->value, $scope); + if (null === $queryString) { + return ParametersAcceptorSelector::selectSingle($functionReflection->getVariants())->getReturnType(); + } + + $resultType = $queryReflection->getResultType($queryString, QueryReflector::FETCH_TYPE_NUMERIC); if ($resultType instanceof ConstantArrayType) { $builder = ConstantArrayTypeBuilder::createEmpty(); foreach ($resultType->getKeyTypes() as $keyType) { diff --git a/src/Extensions/MysqliQueryDynamicReturnTypeExtension.php b/src/Extensions/MysqliQueryDynamicReturnTypeExtension.php index d7c1540b8..66f2e9b7a 100644 --- a/src/Extensions/MysqliQueryDynamicReturnTypeExtension.php +++ b/src/Extensions/MysqliQueryDynamicReturnTypeExtension.php @@ -47,7 +47,12 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, } $queryReflection = new QueryReflection(); - $resultType = $queryReflection->getResultType($args[1]->value, $scope, QueryReflector::FETCH_TYPE_ASSOC); + $queryString = $queryReflection->resolveQueryString($args[1]->value, $scope); + if (null === $queryString) { + return ParametersAcceptorSelector::selectSingle($functionReflection->getVariants())->getReturnType(); + } + + $resultType = $queryReflection->getResultType($queryString, QueryReflector::FETCH_TYPE_ASSOC); if ($resultType) { return TypeCombinator::union( new GenericObjectType(mysqli_result::class, [$resultType]), @@ -67,7 +72,12 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method } $queryReflection = new QueryReflection(); - $resultType = $queryReflection->getResultType($args[0]->value, $scope, QueryReflector::FETCH_TYPE_ASSOC); + $queryString = $queryReflection->resolveQueryString($args[0]->value, $scope); + if (null === $queryString) { + return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + } + + $resultType = $queryReflection->getResultType($queryString, QueryReflector::FETCH_TYPE_ASSOC); if ($resultType) { return TypeCombinator::union( new GenericObjectType(mysqli_result::class, [$resultType]), diff --git a/src/Extensions/PdoQueryDynamicReturnTypeExtension.php b/src/Extensions/PdoQueryDynamicReturnTypeExtension.php index 3f0954edd..838c2e69c 100644 --- a/src/Extensions/PdoQueryDynamicReturnTypeExtension.php +++ b/src/Extensions/PdoQueryDynamicReturnTypeExtension.php @@ -62,7 +62,12 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method } $queryReflection = new QueryReflection(); - $resultType = $queryReflection->getResultType($args[0]->value, $scope, $reflectionFetchType); + $queryString = $queryReflection->resolveQueryString($args[0]->value, $scope); + if (null === $queryString) { + return $defaultReturn; + } + + $resultType = $queryReflection->getResultType($queryString, $reflectionFetchType); if ($resultType) { return new GenericObjectType(PDOStatement::class, [$resultType]); } diff --git a/src/QueryReflection/QueryReflection.php b/src/QueryReflection/QueryReflection.php index a451d4e78..9fb656df8 100644 --- a/src/QueryReflection/QueryReflection.php +++ b/src/QueryReflection/QueryReflection.php @@ -33,9 +33,9 @@ public static function setupReflector(QueryReflector $reflector): void self::$reflector = $reflector; } - public function validateQueryString(Expr $expr, Scope $scope): ?Error + public function validateQueryString(string $queryString): ?Error { - $queryString = $this->builtSimulatedQuery($expr, $scope); + $queryString = $this->builtSimulatedQuery($queryString); if (null === $queryString) { return null; @@ -47,9 +47,9 @@ public function validateQueryString(Expr $expr, Scope $scope): ?Error /** * @param QueryReflector::FETCH_TYPE* $fetchType */ - public function getResultType(Expr $expr, Scope $scope, int $fetchType): ?Type + public function getResultType(string $queryString, int $fetchType): ?Type { - $queryString = $this->builtSimulatedQuery($expr, $scope); + $queryString = $this->builtSimulatedQuery($queryString); if (null === $queryString) { return null; @@ -58,14 +58,8 @@ public function getResultType(Expr $expr, Scope $scope, int $fetchType): ?Type return self::reflector()->getResultType($queryString, $fetchType); } - private function builtSimulatedQuery(Expr $expr, Scope $scope): ?string + private function builtSimulatedQuery(string $queryString): ?string { - $queryString = $this->resolveQueryString($expr, $scope); - - if (null === $queryString) { - return null; - } - if ('SELECT' !== $this->getQueryType($queryString)) { return null; } @@ -78,7 +72,7 @@ private function builtSimulatedQuery(Expr $expr, Scope $scope): ?string return $queryString; } - private function resolveQueryString(Expr $expr, Scope $scope): ?string + public function resolveQueryString(Expr $expr, Scope $scope): ?string { if ($expr instanceof Concat) { $left = $expr->left; diff --git a/src/Rules/SyntaxErrorInQueryFunctionRule.php b/src/Rules/SyntaxErrorInQueryFunctionRule.php index d63c3e8df..bea82ac9b 100644 --- a/src/Rules/SyntaxErrorInQueryFunctionRule.php +++ b/src/Rules/SyntaxErrorInQueryFunctionRule.php @@ -71,7 +71,12 @@ public function processNode(Node $node, Scope $scope): array $errors = []; $queryReflection = new QueryReflection(); - $error = $queryReflection->validateQueryString($args[$queryArgPosition]->value, $scope); + $queryString = $queryReflection->resolveQueryString($args[$queryArgPosition]->value, $scope); + if (null === $queryString) { + return $errors; + } + + $error = $queryReflection->validateQueryString($queryString); if (null !== $error) { $errors[] = RuleErrorBuilder::message('Query error: '.$error->getMessage().' ('.$error->getCode().').')->line($node->getLine())->build(); } diff --git a/src/Rules/SyntaxErrorInQueryMethodRule.php b/src/Rules/SyntaxErrorInQueryMethodRule.php index 8921c1dcb..a48102084 100644 --- a/src/Rules/SyntaxErrorInQueryMethodRule.php +++ b/src/Rules/SyntaxErrorInQueryMethodRule.php @@ -64,7 +64,12 @@ public function processNode(Node $node, Scope $scope): array $errors = []; $queryReflection = new QueryReflection(); - $error = $queryReflection->validateQueryString($args[$queryArgPosition]->value, $scope); + $queryString = $queryReflection->resolveQueryString($args[$queryArgPosition]->value, $scope); + if (null === $queryString) { + return $errors; + } + + $error = $queryReflection->validateQueryString($queryString); if (null !== $error) { $errors[] = RuleErrorBuilder::message('Query error: '.$error->getMessage().' ('.$error->getCode().').')->line($node->getLine())->build(); }