Comments (15)
interessting stuff... the addNull
is there because you added it with #478 for the case of aggregate functions, to enforce it can get null :)
I need to think about it
from phpstan-dba.
I wonder whether these addNull
's are correct or whether we should leave this decision to the SQL AST type inference
from phpstan-dba.
the AST cannot know this I think. fetchSingle will return first column from first row.
For example using your database structure.
$this->database->fetchSingle('select adaid from ada')
AST will tell me that adaid is int<0,max>
and never null
, right? But fetchSIngle will correctly return int<0,max>|null
because it will be null when ada is empty.
But in case
$this->database->fetchSingle('select count(*) from ada')
right now it will return int|null
but in reality it should never be null
from phpstan-dba.
shouldn't the dibi api then also return null
for $this->database->fetchSingle('select count(*) from ada')
when ada is empty? (I am asking stupid questions since I never used dibi)
from phpstan-dba.
no, because it will never be null
, it will be some number (the count), in case of empty table 0
from phpstan-dba.
the motivation behind this is that I started using new phpstan rules https://github.com/shipmonk-rnd/phpstan-rules, ru and it now throws phptan error that I am comparing int|null > int
in code
$count = $this->database->fetchSingle('select adaid from ada');
if ($count > 0) {
....
}
from phpstan-dba.
I see thx.
per your comment
$count = $this->database->fetchSingle('select adaid from ada');
if ($count > 0) {
....
}
can return null, so it will not help you against the error the shipmonk rule is reporting.
it would only help for similar logik with a different query (like your count
case):
$count = $this->database->fetchSingle('select count(adaid) from ada');
if ($count > 0) {
....
}
right?
from phpstan-dba.
yes, my bad, was copying the query and chose the wrong one. should have been the count query
from phpstan-dba.
do other apis like mysqli, mysql, pdo etc also return null
when 'select adaid from ada'
is used on a empty table?
from phpstan-dba.
i do not work with other apis but I havent seen a method that works like fetchSingle
- that returns only the first column from the first row only. They usually have methods to fetch row, fetch assoc but not fetchOneSingle field.
from phpstan-dba.
After my first morning coffee, I think there is an easy solution:
within the class which implements your database access implement
public function fetchCount($query): int {
$count = $this->fetchSingle($query);
if ($count === null) {
throw new RuntimeException('count() can never be null');
}
return $count;
}
and use it instead of what you have right now:
$count = $db->fetchCount('select count(adaid) from ada');
I don't think we can solve it in phpstan-dba itself. I will close the issue now. feel free to comment/discuss further though.
from phpstan-dba.
well there certainly are some dirty workaround that would solve it phpstan-dba, first one coming to mind
--- a/vendor/staabm/phpstan-dba/src/Extensions/DibiConnectionFetchDynamicReturnTypeExtension.php
+++ b/vendor/staabm/phpstan-dba/src/Extensions/DibiConnectionFetchDynamicReturnTypeExtension.php
@@ -88,7 +88,7 @@ final class DibiConnectionFetchDynamicReturnTypeExtension implements DynamicMeth
return null;
}
- $fetchResultType = $this->reduceResultType($methodReflection, $resultType);
+ $fetchResultType = $this->reduceResultType($methodReflection, $resultType, $queryString);
if (null === $fetchResultType) {
return null;
}
@@ -106,7 +106,7 @@ final class DibiConnectionFetchDynamicReturnTypeExtension implements DynamicMeth
return null;
}
- private function reduceResultType(MethodReflection $methodReflection, Type $resultType): ?Type
+ private function reduceResultType(MethodReflection $methodReflection, Type $resultType, string $queryString): ?Type
{
$methodName = $methodReflection->getName();
@@ -117,6 +117,10 @@ final class DibiConnectionFetchDynamicReturnTypeExtension implements DynamicMeth
} elseif ('fetchPairs' === $methodName && $resultType instanceof ConstantArrayType && 2 === \count($resultType->getValueTypes())) {
return new ArrayType($resultType->getValueTypes()[0], $resultType->getValueTypes()[1]);
} elseif ('fetchSingle' === $methodName && $resultType instanceof ConstantArrayType && 1 === \count($resultType->getValueTypes())) {
+ if (str_starts_with($queryString, 'select count(')) {
+ return $resultType->getValueTypes()[0];
+ }
+
return TypeCombinator::addNull($resultType->getValueTypes()[0]);
}
but its too hacky to be merged, I guess :)
from phpstan-dba.
but its too hacky to be merged, I guess :)
absolutely. ;)
and my above example is pretty clean on your end
from phpstan-dba.
yes i guess i will do that since I use my fork of dibi anyway. But might have to do custom phpstan rule that will check query and if it starts with select count(
, it will scream if used with fetchSingle
instead of fetchCount
(since I know I'd forget to use it sometimes)
Ok thanks 👍
from phpstan-dba.
phpstan will cry at you because of the NULL value anyway - but sure why not :)
from phpstan-dba.
Related Issues (20)
- Unexpected query error
- Unexpected query error
- Inconsistency for string in query check between Record and Replay HOT 4
- `PDO::FETCH_KEY_PAIR` errors when selecting not exactly 2 columns
- SqlAst: throw when used with pgsql
- Argument expects a literal string, got literal-string HOT 5
- Connection::insert data inference does not use indicated Types HOT 4
- mysqli: error on invalid escaping HOT 5
- Query AST analysis? HOT 2
- AST doubts regarding null/not-null HOT 4
- AST: inconsistent behavior with functions and aliases HOT 4
- Analyzing multiple connections HOT 6
- Right vs left join HOT 2
- AST: generic operator support HOT 2
- pgsql support for AST HOT 2
- give up sql based narrowing in case sqlftw cannot parse the query
- pgsql support for uuid type
- Support for (PDO->prepare())->execute() HOT 6
- generic type mysqli_result error with phpstan v1.10.36 and v1.10.37 HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from phpstan-dba.