Skip to content

Commit 98f895a

Browse files
staabmclxmstaab
andauthored
prevent wrong type inference on queries containing string (#198)
Co-authored-by: Markus Staab <[email protected]>
1 parent 60865d5 commit 98f895a

File tree

4 files changed

+130
-10
lines changed

4 files changed

+130
-10
lines changed

.phpstan-dba.cache

Lines changed: 52 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.phpunit-phpstan-dba.cache

Lines changed: 52 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/QueryReflection/QueryReflection.php

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public function resolvePreparedQueryStrings(Expr $queryExpr, Type $parameterType
103103
*/
104104
public function resolvePreparedQueryString(Expr $queryExpr, Type $parameterTypes, Scope $scope): ?string
105105
{
106-
$queryString = $this->resolveQueryExpr($queryExpr, $scope, true);
106+
$queryString = $this->resolveQueryExpr($queryExpr, $scope);
107107

108108
if (null === $queryString) {
109109
return null;
@@ -134,7 +134,7 @@ public function resolveQueryStrings(Expr $queryExpr, Scope $scope): iterable
134134
return;
135135
}
136136

137-
$queryString = $this->resolveQueryExpr($queryExpr, $scope, false);
137+
$queryString = $this->resolveQueryExpr($queryExpr, $scope);
138138
if (null !== $queryString) {
139139
yield $queryString;
140140
}
@@ -145,37 +145,37 @@ public function resolveQueryStrings(Expr $queryExpr, Scope $scope): iterable
145145
*/
146146
public function resolveQueryString(Expr $queryExpr, Scope $scope): ?string
147147
{
148-
return $this->resolveQueryExpr($queryExpr, $scope, false);
148+
return $this->resolveQueryExpr($queryExpr, $scope);
149149
}
150150

151151
/**
152152
* @throws UnresolvableQueryException
153153
*/
154-
private function resolveQueryExpr(Expr $queryExpr, Scope $scope, bool $preparedContext): ?string
154+
private function resolveQueryExpr(Expr $queryExpr, Scope $scope): ?string
155155
{
156156
if ($queryExpr instanceof Expr\Variable) {
157157
$finder = new ExpressionFinder();
158158
$queryStringExpr = $finder->findQueryStringExpression($queryExpr);
159159

160160
if (null !== $queryStringExpr) {
161-
return $this->resolveQueryStringExpr($queryStringExpr, $scope, $preparedContext);
161+
return $this->resolveQueryStringExpr($queryStringExpr, $scope);
162162
}
163163
}
164164

165-
return $this->resolveQueryStringExpr($queryExpr, $scope, $preparedContext);
165+
return $this->resolveQueryStringExpr($queryExpr, $scope);
166166
}
167167

168168
/**
169169
* @throws UnresolvableQueryException
170170
*/
171-
private function resolveQueryStringExpr(Expr $queryExpr, Scope $scope, bool $preparedContext): ?string
171+
private function resolveQueryStringExpr(Expr $queryExpr, Scope $scope): ?string
172172
{
173173
if ($queryExpr instanceof Concat) {
174174
$left = $queryExpr->left;
175175
$right = $queryExpr->right;
176176

177-
$leftString = $this->resolveQueryStringExpr($left, $scope, $preparedContext);
178-
$rightString = $this->resolveQueryStringExpr($right, $scope, $preparedContext);
177+
$leftString = $this->resolveQueryStringExpr($left, $scope);
178+
$rightString = $this->resolveQueryStringExpr($right, $scope);
179179

180180
if (null === $leftString || null === $rightString) {
181181
return null;
@@ -186,7 +186,7 @@ private function resolveQueryStringExpr(Expr $queryExpr, Scope $scope, bool $pre
186186

187187
$type = $scope->getType($queryExpr);
188188

189-
return QuerySimulation::simulateParamValueType($type, $preparedContext);
189+
return QuerySimulation::simulateParamValueType($type, false);
190190
}
191191

192192
public static function getQueryType(string $query): ?string

tests/data/pdo-prepare.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,20 @@ public function specifiedArray(PDO $pdo, array $idsToUpdate, string $time)
106106
]);
107107
assertType('PDOStatement<array{adaid: int<0, 4294967295>, 0: int<0, 4294967295>}>', $stmt);
108108
}
109+
110+
public function noInferenceOnBug196(PDO $pdo, array $minorPhpVersions, \DateTimeImmutable $updateDate)
111+
{
112+
$sumQueries = [];
113+
$dataPointDate = $updateDate->format('Ymd');
114+
foreach ($minorPhpVersions as $index => $version) {
115+
$sumQueries[] = 'SUM(DATA->\'$."'.$version.'"."'.$dataPointDate.'"\')';
116+
}
117+
$stmt = $pdo->prepare(
118+
'SELECT '.implode(', ', $sumQueries).' FROM ada WHERE adaid = :package'
119+
);
120+
$stmt->execute(['package' => 'abc']);
121+
// this query is too dynamic for beeing analyzed.
122+
// make sure we don't infer a wrong type.
123+
assertType('PDOStatement', $stmt);
124+
}
109125
}

0 commit comments

Comments
 (0)