diff --git a/.phpunit-phpstan-dba.cache b/.phpunit-phpstan-dba.cache index 7ed5f7727..f20b390e7 100644 --- a/.phpunit-phpstan-dba.cache +++ b/.phpunit-phpstan-dba.cache @@ -194,6 +194,28 @@ 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 @@ -1578,6 +1600,14 @@ )), ), ), + 'SELECT adaid FROM ada WHERE email = \'1\'' => + array ( + 'error' => NULL, + ), + 'SELECT adaid FROM ada WHERE email = \'1\' AND gesperrt = \'1\'' => + array ( + 'error' => NULL, + ), 'SELECT adaid FROM ada WHERE email LIKE ":gesperrt%"' => array ( 'error' => NULL, diff --git a/src/QueryReflection/PlaceholderValidation.php b/src/QueryReflection/PlaceholderValidation.php index c982b6082..15af33b17 100644 --- a/src/QueryReflection/PlaceholderValidation.php +++ b/src/QueryReflection/PlaceholderValidation.php @@ -58,7 +58,7 @@ private function checkErrors(string $queryString, array $parameters): iterable } /** - * @param array $parameters + * @param non-empty-array $parameters * * @return iterable */ @@ -67,16 +67,27 @@ private function checkParameterValues(string $queryString, array $parameters, in $queryReflection = new QueryReflection(); $parameterCount = \count($parameters); + $minParameterCount = 0; + foreach ($parameters as $parameter) { + if ($parameter->isOptional) { + continue; + } + ++$minParameterCount; + } - if ($parameterCount !== $placeholderCount) { + if ($parameterCount !== $placeholderCount && $placeholderCount !== $minParameterCount) { $placeholderExpectation = sprintf('Query expects %s placeholder', $placeholderCount); if ($placeholderCount > 1) { $placeholderExpectation = sprintf('Query expects %s placeholders', $placeholderCount); } - $parameterActual = sprintf('but %s value is given', $parameterCount); - if ($parameterCount > 1) { - $parameterActual = sprintf('but %s values are given', $parameterCount); + if ($minParameterCount !== $parameterCount) { + $parameterActual = sprintf('but %s values are given', $minParameterCount.'-'.$parameterCount); + } else { + $parameterActual = sprintf('but %s value is given', $parameterCount); + if ($parameterCount > 1) { + $parameterActual = sprintf('but %s values are given', $parameterCount); + } } yield $placeholderExpectation.', '.$parameterActual.'.'; @@ -91,10 +102,13 @@ private function checkParameterValues(string $queryString, array $parameters, in } } - foreach ($parameters as $placeholderKey => $value) { + foreach ($parameters as $placeholderKey => $parameter) { if (\is_int($placeholderKey)) { continue; } + if ($parameter->isOptional) { + continue; + } if (!\in_array($placeholderKey, $namedPlaceholders)) { yield sprintf('Value %s is given, but the query does not contain this placeholder.', $placeholderKey); } diff --git a/tests/data/syntax-error-in-prepared-statement.php b/tests/data/syntax-error-in-prepared-statement.php index 956d037aa..2fc89fb3d 100644 --- a/tests/data/syntax-error-in-prepared-statement.php +++ b/tests/data/syntax-error-in-prepared-statement.php @@ -282,4 +282,15 @@ public function noErrorOnLockedRead(Connection $connection, int $limit, int $off FOR SHARE ', [':gesperrt' => 1, ':limit' => $limit, ':offset' => $offset]); } + + public function noErrorInBug174(Connection $connection, string $name, ?int $gesperrt = null, ?int $adaid = null) { + $sql = 'SELECT adaid FROM ada WHERE email = :name'; + $args = ['name' => $name]; + if (null !== $gesperrt) { + $sql .= ' AND gesperrt = :gesperrt'; + $args['gesperrt'] = $gesperrt; + } + + $connection->preparedQuery($sql, $args); + } }