diff --git a/src/QueryReflection/PlaceholderValidation.php b/src/QueryReflection/PlaceholderValidation.php index 719da009..964ae2fc 100644 --- a/src/QueryReflection/PlaceholderValidation.php +++ b/src/QueryReflection/PlaceholderValidation.php @@ -20,7 +20,7 @@ public function checkQuery(Expr $queryExpr, Scope $scope, array $parameters): it $queryStrings = []; $namedPlaceholders = false; - foreach ($queryReflection->resolveQueryStrings($queryExpr, $scope) as $queryString) { + foreach ($queryReflection->resolveQueryStrings($queryExpr, $scope, false) as $queryString) { $queryStrings[] = $queryString; if ($queryReflection->containsNamedPlaceholders($queryString, $parameters)) { diff --git a/src/QueryReflection/QueryReflection.php b/src/QueryReflection/QueryReflection.php index ef8d6c06..aad0d7f6 100644 --- a/src/QueryReflection/QueryReflection.php +++ b/src/QueryReflection/QueryReflection.php @@ -268,7 +268,7 @@ public function resolvePreparedQueryString(Expr $queryExpr, Type $parameterTypes * * @throws UnresolvableQueryException */ - public function resolveQueryStrings(Expr $queryExpr, Scope $scope): iterable + public function resolveQueryStrings(Expr $queryExpr, Scope $scope, bool $resolveNonConstantQueries = true): iterable { $type = $scope->getType($queryExpr); @@ -287,7 +287,12 @@ public function resolveQueryStrings(Expr $queryExpr, Scope $scope): iterable // query simulation might lead in a invalid query, skip those $error = $this->validateQueryString($normalizedQuery); - if ($error === null) { + if ( + $error === null + // late abort the query, so we allow the query simulation/validation to throw + // UnresolvableQueryException + && $resolveNonConstantQueries + ) { yield $normalizedQuery; } } diff --git a/tests/rules/data/syntax-error-in-prepared-statement.php b/tests/rules/data/syntax-error-in-prepared-statement.php index 70182346..537d22f7 100644 --- a/tests/rules/data/syntax-error-in-prepared-statement.php +++ b/tests/rules/data/syntax-error-in-prepared-statement.php @@ -361,4 +361,25 @@ public function bug458(Connection $conn) $table = $this->returnsUnion(); $conn->executeQuery('SELECT * FROM ' . $table . ' LIMIT 1'); } + + /** + * @param array $ids + */ + protected function conditionalUnnamedPlaceholder(Connection $connection, array $ids, int $adaid): void + { + $values = []; + $query = 'SELECT email, adaid FROM ada'; + + $query .= ' AND adaid IN (' . someCall($ids) . ')'; + $values = array_merge($values, $ids); + + if (rand(0, 1) === 1) { + $query .= ' AND email = ?'; + $values[] = 'test@example.org'; + } + + $query .= ' ORDER BY adaid'; + + $connection->preparedQuery($query, $values); + } }