staabm / phpstan-dba

PHPStan based SQL static analysis and type inference for the database access layer
https://staabm.github.io/archive.html#phpstan-dba
MIT License
250 stars 17 forks source link

Unexpected expression type in QuerySimulation #276

Open xPaw opened 2 years ago

xPaw commented 2 years ago
$queries = [ 'SELECT 1' ];

foreach( $queries as $test )
{
    $test = $pdo->prepare( $test ); // reusing variable
    $test->execute();
}

However this doesn't crash:

$test = 'SELECT 1';
$test = Container::Database()->prepare( $test );
$test->execute();

Something about the loop makes it confuse the type. Obviously reusing the variable isn't a good idea (and I fixed it in my code), but it probably shouldn't crash.

Uncaught staabm\PHPStanDba\DbaException: Unexpected expression type [snip] of class PHPStan\Type\Generic\GenericObjectType in phpstan-dba\src\QueryReflection\QuerySimulation.php:117
#0 phpstan-dba\src\QueryReflection\QueryReflection.php(189): staabm\PHPStanDba\QueryReflection\QuerySimulation::simulateParamValueType(Object(PHPStan\Type\Generic\GenericObjectType), false)
#1 phpstan-dba\src\QueryReflection\QueryReflection.php(165): staabm\PHPStanDba\QueryReflection\QueryReflection->resolveQueryStringExpr(Object(PhpParser\Node\Expr\Variable), Object(PHPStan\Analyser\MutatingScope))
#2 phpstan-dba\src\QueryReflection\QueryReflection.php(137): staabm\PHPStanDba\QueryReflection\QueryReflection->resolveQueryExpr(Object(PhpParser\Node\Expr\Variable), Object(PHPStan\Analyser\MutatingScope))
staabm commented 2 years ago

thx for reporting. does your real world example really contains a array of literal strings above the loop? or will it be more complex then that?

I am asking, because we might fix the case you reported, while not fixing your actual problem in case the above example is not realistic

xPaw commented 2 years ago

does your real world example really contains a array of literal strings above the loop?

I did have an array of queries to run, yeah.

staabm commented 2 years ago

I think this could be fixed by resolving the query expression type and look whether it contains a constant string.

if so, return immediately in https://github.com/staabm/phpstan-dba/blob/6bd6e84331c6e15d76868e14444ed20c2aab06b9/src/QueryReflection/QueryReflection.php#L148

staabm commented 2 years ago

Thinking more about it.. a example with more then 1 query is more obvious.

Within the loop the result of the query function would be a union of all possible result types, not just a single one as the initial example might suggest -> https://github.com/staabm/phpstan-dba/pull/290